0

動的データ表示を使用していくつかのプロットを描画しています。

マーカーを画面にレンダリングするための MarkerPointsGraph というクラスを提供します。OnRender メソッドは Render 中に呼び出され、これが適切なマーカー (Circle、Triangle など) の render メソッドを呼び出します。

    protected override void OnRenderCore(DrawingContext dc, RenderState state)
    {
        if (DataSource == null) return;
        if (Marker == null) return;

        var transform = Plotter2D.Viewport.Transform;

        DataRect bounds = DataRect.Empty;
        using (IPointEnumerator enumerator = DataSource.GetEnumerator(GetContext()))
        {
            Point point = new Point();
            while (enumerator.MoveNext())
            {
                enumerator.GetCurrent(ref point);
                enumerator.ApplyMappings(Marker);

                //Point screenPoint = point.Transform(state.Visible, state.Output);
                Point screenPoint = point.DataToScreen(transform);

                bounds = DataRect.Union(bounds, point);
                Marker.Render(dc, screenPoint);
            }
        }

        Viewport2D.SetContentBounds(this, bounds);
    }

/// <summary>Renders circle around each point of graph</summary>
public class CirclePointMarker : ShapePointMarker {

    public override void Render(DrawingContext dc, Point screenPoint) {
        dc.DrawEllipse(Fill, Pen, screenPoint, Size / 2, Size / 2);
    }
}

今、私の呼び出しコードは以下の通りです。

        plotter.AddLineGraph(
            data.Data,
            new Pen
            {
                Brush = Brushes.Violet,
                DashStyle = DashStyles.DashDot,
                Thickness = 3
            },
            GetMarker(data),
            new StandardDescription(data.Title));

パフォーマンスで気付いた主な違いは、以下のメソッドにあります。

ChartData クラスからのデータの参照

private ShapePointMarker GetMarker(ChartData data)
    {
        ShapePointMarker marker = null;

        switch (data.MarkerShape)
        {
            case Shapes.Circle:
                marker = new CirclePointMarker();
                break;

            case Shapes.Triangle:
                marker = new TrianglePointMarker();
                break;

            case Shapes.None:
            default:
                marker = null;
                break;
        }

        if (marker != null)
        {
            //Referring to stuff here.
            marker.Fill = new SolidColorBrush(data.MarkerColor);
            marker.Size = data.MarkerSize;
        }

        return marker;
    }

参照の代わりにデータをハードコーディングします。

private ShapePointMarker GetMarker(ChartData data)
    {
        ShapePointMarker marker = null;

        switch (data.MarkerShape)
        {
            case Shapes.Circle:
                marker = new CirclePointMarker();
                break;

            case Shapes.Triangle:
                marker = new TrianglePointMarker();
                break;

            case Shapes.None:
            default:
                marker = null;
                break;
        }

        if (marker != null)
        {
            //Hard coding stuff here.
            marker.Fill = Brushes.Red;
            marker.Size = 5;
        }

        return marker;
    }

GetMarker メソッドの参照ベースのデータをハードコードされた値に変更するだけで、レンダリング時間が 100 倍近く改善されました。

この違いの原因となる C# の動作は何ですか?

編集: MarkerPointsGraph は、各ポイントのマーカーのオブジェクトを作成しません。render メソッドを呼び出すだけです。

4

2 に答える 2

1

ブラシをフリーズしてみてください。

if (marker != null)
{
    Brush b = new SolidColorBrush(data.MarkerColor);
    b.Freeze();  
    marker.Fill = b;  
    marker.Size = data.MarkerSize;  
}

Brushes.Redすでに凍結されているため、パフォーマンスが向上する可能性があります。

于 2013-01-30T19:37:10.397 に答える
1

セットアップについてあまり知らなくても、問題はSolidColorBrush比較的タイトなループで を作成しているという事実にある可能性があります (それらを破棄していませんが、それは別の問題です)。そのオブジェクトには、新しいオブジェクトの作成に関連するかなりの量のオーバーヘッドがありますが、Brushes.Red使用は同じインスタンスを使用するため、同じ問題はありません。一度独自のブラシを作成した場合、同じ問題は発生しないと思います。

于 2013-01-30T19:39:44.953 に答える