Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can WPF render a line path with 300,000 points on it in a performance-sensitive environment?

A simple XY line graph: The X axis will represent the complete range of possible rating percentages, from 0% on one end to 100% on the other. Specifically, the X value will represent our rating cut-off, or the minimum rating a transaction can have before it is no longer acceptable. The Y axis will show values from 0 to the total number of transactions that have come through. The Y value will represent the total number of transactions that have a rating greater than the current X value (or greater than or equal to the current X value, I haven't decided yet). No transactions will have come through when this graph is first drawn, so the graph will begin at "y=0x".

Let's say the first transaction comes through, with a rating of 40%. The rating of the transaction indicates that this transaction is acceptable if our rating cut-off is less than 40%. (... or less than or equal to 40%. Again, I haven't decided yet).

First, the Y axis will rescale to show the range of 0-1 (since 1 is the total number of transactions). Then the line will be modified to indicate that 0 transactions are acceptable from x=40 or more, and that 1 transaction is acceptable from x=40 or less. This is easy to accomplish in WPF by simply adding two points to the line path - one at (40,0) and the other at (40,1) - and then moving the line's left endpoint to (0,1). The line's right endpoint will remain at (100,0). This process can then be repeated for the second transaction, and so on.

The problem is that we will be dealing with six-digit quantities of transactions. and I want to make sure I am using WPF's hardware accelerated vector drawing capabilities to their fullest extent to ensure the graph doesn’t lag or freeze the rest of the program as it tries to render 300,000 points onto a single line path. Or is WPF supposed to be able to handle numbers like that in a heartbeat? I need to find a way to implement this graph without slowing the application to a halt. I have faith that WPF's vector drawing platform will provide a solution, but I don't know enough about how to exploit WPF to be certain that I am getting the most out of WPF's high-performance rendering capabilities.

like image 921
Giffyguy Avatar asked Jun 11 '09 18:06

Giffyguy


4 Answers

I just stumbled upon this post and am building a line graph control myself that needs to be very performant as we update the points on our lines in a real-time manner.

If performance and number of Visual(s) are what you are after ... I doubt you will find a more performant approach than programming directly against WPF's Visual layer (links: 1, 2). My initial results from using this approach have been very positive.

This will be even more performant than overriding OnRender as it will encourage you to take advantage of WPF's retained mode drawing subsystem (where all the drawing instructions are cached).

That is, if all you have to update is a point on the line, then updating the point will force the line Visual to update but won't force the rest of the graph (axes, gridlines, ...) to update ... as the drawing instructions for these are retained and will be reused (since they aren't updating).

Chapter 14 in Pro WPF in C# 2008 by Matthew MacDonald has a great section (titled 'Visuals') on programming against WPF's Visual layer. Chapter 2 of WPF Control Development Unleashed also has section on page 13 where he discusses how a DrawingVisual approach would be perfect for a charting component. Finally, Charles Petzold wrote a MSDN Magazine article where the best overall solution to a scatter plot was a DrawingVisual approach.

(Now, I know that your question mentioned the axes will also be updating ... and so my answer is really for the general case ... but I still think that this approach will be the most performant ... as only the things that need updating ... will update.)

like image 70
cplotts Avatar answered Nov 02 '22 16:11

cplotts


If you want it to be fast, the best way is to derive from Control and implement OnRender - normally this isn't necessary, but for your application it might be.

Also, let's take a step back - the screen you're rendering to certainly isn't 300k pixels across; before you go to render, reduce the buffer by averaging n nodes into one until you've got something closer to the resolution of the actual device, then draw it on-screen.

like image 44
Ana Betts Avatar answered Nov 02 '22 16:11

Ana Betts


I do not know the answer, but coding up a quick test shouldn't take much longer than it did for you to post. Also, see this thread for a similar discussion.

like image 4
PeterAllenWebb Avatar answered Nov 02 '22 16:11

PeterAllenWebb


It might be worth having a look at the WPF DynamicDataDisplay library. I've been using it recently and haven't any problems with large amounts of data. It's only an early version (0.3 in fact) so there's not much documentation, but it does have samples showing how to use it. Hopefully that'll be enough to get you started.

The SimulationSample generates lots of data, so that should be a good place to start.

like image 4
Wilka Avatar answered Nov 02 '22 15:11

Wilka