C#渲染性能差异

时间:2013-01-30 19:05:47

标签: c# performance rendering

我正在使用动态数据显示绘制一些图。

它提供了一个名为MarkerPointsGraph的类,用于将标记渲染到屏幕上。在渲染期间调用OnRender方法,然后调用相应的标记(圆形,三角形等)渲染方法。

    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不为每个点创建Marker对象。它只调用render方法。

2 个答案:

答案 0 :(得分:1)

您可以尝试冻结画笔:

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

Brushes.Red已经冻结,这可能是您看到效果提升的原因。

答案 1 :(得分:1)

在不了解您的设置的情况下,您的问题可能在于您在相对紧凑的循环中创建SolidColorBrush(并且不处理它们,但这是另一个问题)。该对象具有与创建新对象相关的相当大的开销,而使用Brushes.Red使用相同的实例,因此没有相同的问题。如果你想创造自己的画笔,我认为你不会看到同样的问题。