sourcenouveau
sourcenouveau

Reputation: 30524

Increasing performance of graphical charts with high data rates

I would like to create line chart with thousands of points that completely refreshes at least 10 times per second. What are some techniques for increasing the performance of charts with a lot of data to display?

One idea I've had is to change the number of draw calls from being based on the number of data points to being based on the number of pixels available. I could divide the data into bins along the X axis and draw a vertical line between the min and max for each bin.

Upvotes: 5

Views: 2506

Answers (6)

Pasi Tuomainen
Pasi Tuomainen

Reputation: 516

  1. Use GPU acceleration. DirectX, OpenGL, Vulkan, Metal, WebGL. Write shaders that do part of the computation.
  2. Then optimizing the data input without quality loss, and writing rendering routines with minimum amount of function/method calls and with action you do, evaluate the CPU for that action. Thoroughly performance-profile your application.
  3. Animate the transitions, if data rate is low.
  4. If the chart is too slow, then downsampling. (We don't do it actually).

With these principles, we have wrote .NET WPF charts that can monitor 8 billion data points, and JavaScript charts up to 100 million data points. I'm one of the developers of LightningChart.

Upvotes: 0

Disclosure: I own ABT Software and was directly involved in the development of SciChart

Unfortunately no WPF-based chart using the Retained mode graphics pipeline is able to cope with high datarate scenarios. As a result, I've created a high performance WPF/SL chart component called SciChart to cope with these sorts of scenarios. SciChart seeks to fill the gap for ultra high performance scientific / stock charts and as part of its optimisation it uses proprietary resampling algorithms to reduce the dataset before drawing.

In response to your question, I would suggest taking a look at the Nyquist Frequency theory (used in Digital Signal Processing). This states the minimum number of datapoints required to accurately discretise a waveform is 2x the sampling frequency. In the case of an audio signal for instance, a sampling frequency of 44kHz (for Audio CDs) can accurately represent a maximum frequency of Fs/2 or 22kHz. In the case of a chart, the Nyquist frequency is 2x pixel width - this is the minimum number of datapoints required to accurately discretise frequencies up to and including the pixel width.

Please note that this is a bare minimum and you will experience aliasing. To get around this, you either need an antialiasing filter prior to the resampling stage and/or need higher multiples of points.

Resampling algorithms are quite well known and fast implementations are available. I would suggest resampling to multiples of your pixel width and applying AA to get the best results.

Upvotes: 0

Chris Grant
Chris Grant

Reputation: 2385

There is a good article about charting performance over on the Visiblox blog, here.

You might not be using this particular charting library in your application, but the main points of the article will still apply. Its all about carefully selecting what you need to show when. The main points of the article are:

  • Consider carefully the type of series to use
  • Where possible set explicit ranges on the axes
  • Remove points that are offscreen from the DataSeries
  • Remove data generation from the UI thread
  • Reduce or disable animations
  • Think carefully about the amount of data and the frequency of updates

There's also a slightly less helpful article on the MSDN blog, but it should help to outline some of the key areas when improving chart performance.

Upvotes: 5

aL3891
aL3891

Reputation: 6275

Generally speaking you could do a coule of things:

  • Delta updates. Only redraw bits of the graph where data has changed. You could for example simply translate the pixels in the graph to the left and only draw the fresh data instead of redrawing the whole thing.
  • Sample data. As you describe, your data might be so dense that its not be meaningful to draw every single point. Based on the zoom level for the graph you can drop some of the data points.
  • Redraw based on device framerate not data rate. There is no point in redrawing the graph faster than it can be displayed, dont queue up another redraw if one is already in progress. Doing that can clog the message queue that most ui depends on and result in stuttering ui.

A nice trick by the way is to draw a vector line with some number of points that will represent the resolution of your graph [number of horizontal pixels for example], you can then have data 'move though' the vector of points in the line like a queue, where you'd shift the elements 'to the left' before you add a new data point. In Wpf terms this will result in a 'virtualized' graph, meaning that the ui element is a constant and animated instance as opposed to being re-instanciated when new data comes in.

An opposite example would be to add a new vector line between the last point and the new point when new data is available. (I'm assuming that a high level graphics api is used where lines/shapes are discreet objects, if not, 'virtualization' isnt really applicable)

Upvotes: 3

Vitalij
Vitalij

Reputation: 4625

If the you need to have a good performance during user manipulation, you could do the following:

  1. When users starts an interaction with the chart, create a simplified version of it, lets say at maximum 30 datapoints would be present in that chart.

  2. Let the user finish his manipulation

  3. Fill chart with all data points ( you might use a sampling algorithm here as well, as it doesn't make sense to render more points than the resolution of the screen)

    Using that approach you chart will be very responsive while being manipulated (with fewer detailed though) and detailed while static.

Upvotes: 2

richmb
richmb

Reputation: 1595

Is that high of a resolution really required to actually be displayed or is it just used for internal calculations. you could possibly do some internal averaging/compression of the points before you call your draw function so you'll be displaying less points.

Upvotes: 0

Related Questions