Sep 21, 2010 at 3:45 AM
Edited Sep 21, 2010 at 3:52 AM
@alexis_michel: Can of bird names it is ;).
I do think you took this personally for one reason or the other. Before you dive into this sort discussion, please test the samples for yourself. Execute SimulationSample.exe 4 times so that you have 4 instances running. Each running
sample has only one chart. If you believe that is an unfair test, take the sample code and paste it 4 times into a WrapPanel so that all the charts fit nicely in one window, and is inside one process. Now run the process. If you do better
than 50% CPU on an average machine, let us know.
Also Im not sure what sort of software development school is teaching developers to max out the CPU or memory on a machine. Did you happen to notice that the windows operating system is close to unresponsive with an application running at those levels?
Fundamentally what we are taking about here is a problem with WPF in and of itself as far as charting goes. The problem lies in the System.Windows.Shapes namespace. Take the simple case of the Line class in System.Windows.Shapes. In order
to draw 1 line four coordinates need to be set - X1, Y1, X2, and Y2 - each of which is exposed as a .NET property of type double. Now draw a line once every second, NOT 200 times a second. It is well known that even the individuals with the best
eyesight strain to distinguish beyond 50 frames per second. Now what happens when we set one of these coordinates?
[ This is actual .NET 3.5 framework code ]
public void set_X1(double value)
..and what happens inside setValue?
public void SetValue(DependencyProperty dp, object value)
PropertyMetadata metadata = this.SetupPropertyChange(dp);
this.SetValueCommon(dp, value, metadata, false, OperationType.Unknown, false);
So what does this all mean? What exactly are we talking about here? First there is a boxing operation when a double value is implicitly converted into System.Object. Then SetValue causes a DependencyPropertyChanged. Now do this for
all 4 coordinates. Now say a chart is made up of 50 lines, so do this 50 times for each line - remember all the coordinates on the chart will be redrawn every time there is an update. Now do all this once per second, i.e. 60 times a minute. Now
keep doing this for one hour, assuming you keep the chart running for an hour. So what do we finally have?
After one hour we have 4 * 50 * 60 * 60 = 720,000 Dependency Property Changes and 720,000 boxing operations. And that is for only one chart, updating once a second.
Now imagine having 4 charts, running for 4 hours under the same scenario? 11,520,000. That is over 11 million boxing operations and DP changes!
So while WPF is great framework -- System.Windows.Shapes which all WPF charts seem to be based on, doesn't seem to be that agreeable. It is as if it was added onto .NET as an afterthought without much thought how it will actually work with live graphics.
I believe it is because of limitations like these other contributors of D3 have started writing a DirectX version of D3. See the following thread: http://dynamicdatadisplay.codeplex.com/Thread/View.aspx?ThreadId=74901. A barebones version
of this code is available in the nightly build in the downloads section of this project.
So the real question is, how does a developer with a limited amount of time work around this? One is to implement their own charts with classes in the System.Windows.Media.Drawing namespace. The other and more simpler way, is to have a queueing mechanism
for their observable collection so as to display limited number of live datapoints at any one time, as new points are queued and displayed, older points are dequeued and fall of the chart. I have actually tried this, and performance-wise it works out
Of couse one could also consider embedding charting packages that use ActiveX, DirectX or other technologies, but they will not have inherent support for themes.
@alexis_michel please try to restrain yourself if you do not actually have something useful or productive to add ;). Unless of course you work for microsoft and have taken an unspoken offense.