Version

Chart Performance

Overview

This topic is your gateway to important conceptual and task-based information that will help you make the XamDataChart™ control work as fast as possible in your application.

The topic is organized as follows:

Introduction

Although the XamDataChart is capable of handling high volumes of data, there are several chart features that affect performance of the chart and they should be considered when optimizing performance in your application. Also, there are a few data patterns that should be considered while implementing the data source for the XamDataChart control.

Chart Features

The following section lists chart features that add to the overhead and processing updates in the XamDataChart control.

Series Types

The number of series defined in the XamDataChart control’s Series collection contributes to the performance of the chart. Also, the type of series has some impact on the chart; for example, using LineSeries is recommended over usage of SplineSeries because of the complex interpolation of spline lines between data points. The same applies to PolarLineSeries and PolarSplineSeries or PolarSplineAreaSeries.

This code snippet shows how to replace SplineSeries with LineSeries in the XamDataChart control.

In XAML:

<ig:XamDataChart x:Name="DataChart" >
      <ig:XamDataChart.Series>
            <ig:SplineSeries ItemsSource="{Binding}"
                             ValueMemberPath="Value"
                             XAxis="{x:Reference categoryXAxis}"
                             YAxis="{x:Reference numericYAxis}">
            </ig:SplineSeries>
            <ig:LineSeries ItemsSource="{Binding}"
                           ValueMemberPath="Value"
                           XAxis="{x:Reference categoryXAxis}"
                           YAxis="{x:Reference numericYAxis}">
            </ig:LineSeries>
      </ig:XamDataChart.Series>
</ig:XamDataChart>

In C#:

var splineSeries = new SplineSeries();
splineSeries.DataSource = data;
splineSeries.ItemsSource = data;
splineSeries.ValueMemberPath = "Value";
splineSeries.XAxis = this.categoryXAxis;
splineSeries.YAxis = this.numericYAxis;
this.DataChart.Series.Add(splineSeries);var lineSeries = new LineSeries();
lineSeries.DataSource = data;
lineSeries.ItemsSource = data;
lineSeries.ValueMemberPath = "Value";
lineSeries.XAxis = this.categoryXAxis;
lineSeries.YAxis = this.numericYAxis;
this.DataChart.Series.Add(lineSeries);

Series Resolution

Setting the Resolution property on a Series to a higher value can help with performance, but it will lower the graphical fidelity of the line. As such, it can be increased up until the fidelity is unacceptable.

This code snippet shows how to increase resolution of a series in the XamDataChart control.

In XAML:

<ig:XamDataChart x:Name="DataChart" >
      <ig:XamDataChart.Series>
            <ig:LineSeries Resolution="1.5" />
      </ig:XamDataChart.Series>
</ig:XamDataChart>

In C#:

LineSeries series = new LineSeries();
series.Resolution = 1.5;

Markers

Markers are especially expensive when it comes to performance of the Data Chart because they add to the layout complexity of the chart, and perform data binding to obtain certain information. An additional layout complexity still adds to the overhead. Therefore, if markers are not needed, they should be removed from the chart by setting the MarkerType property of a Series to MarkerType enumerable value.

This code snippet shows how to remove markers from the XamDataChart control.

In XAML:

<ig:XamDataChart x:Name="DataChart" >
      <ig:XamDataChart.Series>
            <ig:LineSeries MarkerType="None" />
      </ig:XamDataChart.Series>
</ig:XamDataChart>

In C#:

var series = new LineSeries();
series.MarkerType = MarkerType.None;

Axes Types

XAxis property. However, usage of CategoryDateTimeXAxis is not recommended if spaces between data points, based on the amount of time span between them, are not important. Instead, CategoryXAxis should be used because it is more efficient in the way it coalesces data, and it doesn’t perform any sorts on the data like the CategoryDateTimeXAxis does.

This code snippet shows how to replace CategoryDateTimeXAxis with CategoryXAxis in the XamDataChart control.

In XAML:

<ig:XamDataChart.Axes>
    <ig:CategoryXAxis x:Name="categoryXAxis"
                      ItemsSource="{Binding}"
                      Label="Date">
    </ig:CategoryXAxis>
    <ig:CategoryDateTimeXAxis x:Name="categoryDateTimeXAxis"
                      ItemsSource="{Binding}"
                      DateTimeMemberPath="Date"
                      Label="Date">
    </ig:CategoryDateTimeXAxis>
</ig:XamDataChart.Axes>

In C#:

var categoryXAxis = new CategoryXAxis();
categoryXAxis.Label = "Date";
var categoryDateTimeXAxis = new CategoryDateTimeXAxis();
categoryDateTimeXAxis.DateTimeMemberPath = "Date";
categoryDateTimeXAxis.Label = "Date";
Note
Note:

Turning off the axis gridlines does not currently improve the performance of the XamDataChart.

Axis Labels

If labels are not used, they should be turned off on Axis.

This code snippet shows how to hide axis labels in the XamDataChart control.

In XAML:

<ig:XamDataChart.Axes>
    <ig:CategoryXAxis x:Name="axis" LabelVisibity="Collapsed" />
</ig:XamDataChart.Axes>

In C#:

var axis = new CategoryXAxis();
axis.LabelVisibility = Visibility.Collapsed;

Axis Label Extent

The chart control adjust at runtime extent of labels on y-axis based on a label with longest value. This might decrease chart performance if range of data changes and labels need to be updated. Therefore it is recommended to set label extent at design time in order to improve chart performance. The following code snippet shows how to set a fixed extent for labels on y-axis in the XamDataChart control.

In XAML:

<ig:XamDataChart.Axes>
    <ig:NumericYAxis x:Name="numericYAxis"
                     LabelExtent="50" />
</ig:XamDataChart.Axes>

In C#:

var axis = new NumericYAxis();
axis.LabelExtent = 50;

Data Implementation

Data Source

If changing only one or two points in data that is bound to the Series object’s ItemsSource property, you should avoid sending the Reset event from the INotifyCollectionChanged interface because the XamDataChart control is optimized to better handle several Add, Remove, Replace, and Move events from the INotifyCollectionChanged interface. Sending one reset event instead of several smaller events can have a higher net cost than a lot of smaller operations with the ItemsSource performed in the same interaction.

This code snippet shows how to notify about changes in custom collection using the Add event action instead of the Reset event action when a new data point is added to the collection.

In C#:

using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using NotifyEventArgs = System.Collections.Specialized.NotifyCollectionChangedEventArgs;
using NotifyAction = System.Collections.Specialized.NotifyCollectionChangedAction;
public class DataCollection : INotifyCollectionChanged, IEnumerable
{
        protected List<DataPoint> Data = new List<DataPoint>();
        public event NotifyCollectionChangedEventHandler CollectionChanged;
        protected void OnCollectionChanged(NotifyEventArgs e)
        {
            if (CollectionChanged != null)
            {
                CollectionChanged(this, e);
            }
        }
        public IEnumerator GetEnumerator()
        {
            return this.Data.GetEnumerator();
        }
        public void Add(DataPoint dataPoint)
        {
            this.Data.Add(dataPoint);
            NotifyEventArgs e = new NotifyEventArgs(NotifyAction.Add, dataPoint);
            // use the Add event action instead of the Reset event action
            // when adding only one or two points to the collection
            //NotifyEventArgs e = new NotifyEventArgs(NotifyAction.Reset);
            this.OnCollectionChanged(e);
        }
}

Data Items

If the values of the data items in the bound collection won’t change their values, a faster alternative is to not implement the INotifyPropertyChanged interface.

If they do implement this interface, the data binding engine of the XamDataChart control assumes it has to register handlers for each of them, and this increases overhead.

This code snippet shows a data item with and without implementation of the INotifyPropertyChanged interface.

In C#:

using System.ComponentModel;
public class DataPoint
{
    #region Properties
    public double X { get; set; }
    public double Y { get; set; }
    #endregion
}
public class ObservableDataPoint : INotifyPropertyChanged
{
    #region Porperties
    private double _x;
    private double _y;
    public double X
    {
        get { return _x; }
        set { if (_x == value) return; _x = value; this.OnPropertyChanged("X"); }
    }
    public double Y
    {
        get { return _y; }
        set { if (_y == value) return; _y = value; this.OnPropertyChanged("Y"); }
    }
    #endregion
    #region Event Handlers
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
    }
    protected void OnPropertyChanged(PropertyChangedEventArgs propertyChangedEventArgs)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
            handler(this, propertyChangedEventArgs);
    }
    #endregion
}