We are using RadChart version 2009.3.1322.35.
The chart is declared in XAML and databound to an ObservableCollection of DataPoints. The collection contains 9000 data points, which makes the chart take 1 minute to display.
How can we improve the performance of the chart to accomodate thousands of data points?
Note: we have already set ChartArea EnableAnimations to false.
16 Answers, 1 is accepted
Here is a list of some simple changes that can improve the performance in large data scenarios like this one:
- Use fewer data points -- typical performance guidance for Silverlight and WPF recommends capping the total number of UI elements in the low- to mid-hundreds. Given that each of the chart item instances instantiates around 3-5 UI elements, trying to render a chart with 1000 data points can start to bog the system down quite fast. Note that the Q1 2010 edition of RadChart will be able to handle hundred of thousands of data points thanks to its new Virtual Scrolling and Data Sampling mechanisms that are currently being developed.
- Disable animations -- you have already done that.
- Simplify the chart item control template -- e.g. the Line item template contains by default item label as well as point mark visual that can be removed (as they are relatively insignificant when rendering thousands of records); with lots of points the sheer number of UI elements simply bogs the system down as discussed above so if you cannot reduce the data points, you will need to simplify the chart item control template (note that simply changing their Visibility will not do the trick, they should be physically removed from the template).
- Specify fixed axis range manually -- if your data changes a lot but you know the ranges over which it will vary, you can disable the Axis auto-range algorithm and specify the Axis range manually -- this will probably lower the processing time a bit.
- Add the points more efficiently (ObservableCollection scenario) -- the control is built around a model where any changes to the data are automatically shown on the screen. This is accomplished by detecting classes that implement the INotifyPropertyChanged interface and collections that implement the INotifyCollectionChanged interface and registering to find out about changes as they occur. However, this system can be counterproductive in one scenario: starting with an empty collection and adding a bunch of data points all at once. By default, each new data point generates a change notification which prompts RadChart to re-analyze the data, re-compute the axis properties, re-layout the visuals, etc. It would be more efficient to add all the points at once and then send a single notification to the control that its data has changed. Unfortunately, the otherwise handy ObservableCollection class doesn't offer a good way of doing this but it is pretty easy to add:
Hope this helps.
the Telerik team
Thank you very much for your fast and thorough response.
We have come up with short-term and long-term solutions:
In the short-term, we are plotting fewer points (under 500 points) and the RadChart [using default properties] performance is perfectly acceptable.
In the long-term, we must plot up to 10,000 points. So we are trying out your suggestions. So far I've implemented your "Add the points more efficiently" recommendation and that has helped, but not enough. My next steps are to implement your "Simplify the chart item control template" and "Specify fixed axis range manually".
We are grateful for your fast, courteous and informative support.
I am currently using the beta version of Q1 2010, and love the scroll/zoom feature, but I am having a problem when plotting multiple lines. The performance appears to decrease quite a bit. I currently have 6 lines to display and have approx 1800 points per line. In the near future, I will have to ramp up the number of data points per line to approx. 86400 data points. I have disabled all animations. Our current solution is to reduce the number of data points per line and that seems to speed up the process a little bit, but I would rather not have to do that if at all possible. Any suggestions?
Generally, when populating the chart control with large number of data points you can achieve the best rendering performance if you enable the "Fast Line" mode of the Line series (i.e. set LineSeriesDefinition.ShowItemLabels, ShowPointMarks, and ShowToolTips properties to false -- this should grant you decent performance for 6 x 1800 items series even with the sampling mechanism disabled (RadChart.SamplingSettings.SamplingThreshold = 0).
However, if you would like to display 6 x 90,000 items in RadChart, you will need to enable the new sampling as well (the sampling mechanism basically works much like SQL Server grouping and is able to downsample millions of records to the SamplingThreshold value -- i.e. with the default SamplingThreshold = 200, any number of records bound to a series is downsampled to 200 actual data points).
Find attached a sample application as well.
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
The sampling and performance of RadChart's ability to show thousands of data points in an intelligent way is great. The biggest problem for me is how to transfer this data from the server to client. In a real world scenario, this data is going to reside in a persistent store like database and a WCF service will help getting it.
All the example's I've seen so far works with random data generation on the client side. How can I efficiently bring such a large volume of data from a WCF service.
I believe the sampling only occurs on the client side after you have bound all the datapoints, series mapping to the chart.
Many Thanks in Advance.
Generally Silverlight is a client-side technology therefore all of the control logic (e.g. the built-in chart sampling and aggregation) can be executed only on the client-side. Basically if you would like to use the chart sampling feature, you will need to send all data through a WCF service and this will not be very efficient; alternatively you can try to group / aggregate your data on the SQL SERVER level (i.e. in this scenario you will not use chart sampling feature) and pass to the client only the actual data to display (versus sending all data).
Here are some nice materials on WCF RIA to get you started:
- RIA & Silverlight Clients: http://msdn.microsoft.com/en-us/library/ee707349%28VS.91%29.aspx.
- Brad Abrams series of blog posts:http://blogs.msdn.com/brada/archive/tags/RIAServices/default.aspx.
the Telerik team
Does the sampling also work when you create the DataSeries yourself (without SeriesMapping)?
Data Sampling is only supported in databound scenarios.
the Telerik team
We are also utilizing thousand of data points. But instead of starting with an empty collection and adding thousands of datapoints (we have the collection populated and bind once, which works fine), we need to update all the datapoints at the same time.
Again, by default, each datapoint update generates a change notification and the RadChart re-analyses the data (which takes long, varying on the number of datapoints)
We're trying to update the information more efficiently, similar to the example of adding points more efficiently:
While this functions (update messages are now not sent automatically and we can force the RadChart to refresh once all the points are updated), the update process still takes the same time. In comparason, the initial binding takes only a second.
Is there something missing in our implementation causing the RadChart to re-analyze the data datapoint by datapoint?
While it is not explicitly clear what exactly what happens from the code pasted my advice to you would be to simply rebind the chart when you have large amount of changes to your data. However, if you are using an ObservableCollection as the data source and you update the data source collection this will cause RadChart to update itself on each change.
The best way to batch update the chart would be to use a non ObservableCollection as source (or if you need to use such a collection, refrain from updating that instance) and simply generate a new updated collection and set the chart control ItemsSource to the new collection effectively swapping it with the old one.
All the best,
the Telerik team
We are finding that scrolling and zooming operations are very slow, taking around 5 seconds for a single scroll. Profiling the application while scrolling shows that the chart's Rebind() method is called on scrolling, which is taking up all of the time. Is there a way around this behaviour?
We are currently looking into this issue as described in your support ticket. We will have some information to you soon.
All the best,
the Telerik team
In your answer you say to simplify the control template and take out the point & labels of the line series. I am having trouble extracting the Line template from Expression Blend. Can you please describe how to get the Line Control Template out in Expression Blend. The Bar one comes out easy enough, but not the Line (or Area).
With more recent versions of the control it is not necessary to manually simplify the control template in Blend. If you set all of the SeriesDefinition.ShowItemLabels, SeriesDefinition.ShowPointMarks, and SeriesDefinition.ShowItemToolTips properties to false, the labels and pointmarks will not be generated at all (and thus they will not be rendered as well).
You can take a look at the RadChart's Performance Tips and Tricks help article. However, I want to note that RadChart is the old charting component from the UI for WPF suite. The new RadChartView resolves many of the issues and limitations of RadChart. Also, it has better implementation and improved performance. Moreover, it is quite easy to set up and very flexible when it comes to customization. You can read more about the differences between the charts in the RadChart vs. RadChartView help article.
I recommend you to check the new charting components and see if they work for you. Also, you can see the 5 Easy Steps Towards a Fast Chart blog post.