1

My Situation: I am currently working on a project that graphs large amount data from several industrial machines. The project is a Winforms/C# project. Currently I am using the DrawLine method from the Graphics object provided by the "System.Drawing" namespace. When piloting graphs with more than 500+ points or so, the lag is very noticeable and even causes the paint method to time out. To be clear, I am interested in developing my own graphing program and not wanting to use another preexisting one.

My Observation: When traversing the internet I can see graphs like the one below. My assumption is that even though in the graph below there is five or six points plotted, there must be hundreds of "intermediate" points plotted in between the actual data points(to get the smooth curve between each data point). Graphs like these are very smooth with resizing.

enter image description here

My Question:

How could I get the performance that some of these modern(super user friendly) graphing programs enjoy?

Robo Maklen
  • 152
  • 1
  • 11
  • Also [netgraph](http://www.gigasoft.com/netgraph.html) – JSteward Jul 23 '18 at 21:22
  • @JSteward How is this a duplicate?? I am asking how to implement a graphing program efficiently, not using some else's. – Robo Maklen Jul 23 '18 at 21:29
  • 1
    That answer points to Microsoft Chart Controls for WInForms is that not what you're looking for? Or are you going to write your own charting library? – JSteward Jul 23 '18 at 21:33
  • Writing my own. I thought I made that clear under "My Situation" but edited it to make it even more clear. @JSteward – Robo Maklen Jul 23 '18 at 21:34
  • Ah fair enough then good luck, flag retracted. – JSteward Jul 23 '18 at 21:35
  • 1
    @JMaklen look on [Double buffering](https://msdn.microsoft.com/en-us/library/system.drawing.bufferedgraphics(v=vs.110).aspx), to improve performance of rendering, if you're not already doing that. for smooth curving you might look into something like [Cardinal Splines](https://msdn.microsoft.com/en-us/library/7ak09y3z(v=vs.110).aspx), as in your case you actually have a lot of points, and just want to draw smooth transition between them. This might help. – Tigran Jul 23 '18 at 21:39
  • @JMaklen: look on this one too: http://csharphelper.com/blog/2015/04/draw-a-smooth-curve-connecting-points-in-c/ and read comments too. – Tigran Jul 23 '18 at 21:48
  • @Tigran WOW! Double buffering is like magic. Why do you think it is not set to true by default? – Robo Maklen Jul 23 '18 at 23:25
  • Look on this: https://stackoverflow.com/questions/252689/why-does-the-doublebuffered-property-default-to-false-on-a-datagridview-and-why – Tigran Jul 24 '18 at 00:03
  • DB is set to true for PictureBox, which is what you should draw on. You still didn't tell us WHY you don't want to use MSChart. You show a typical area chart.. – TaW Jul 24 '18 at 06:33
  • I do not want to use a Chart Program because I was given a preexisting chart program to make better. Plus I would like to do my own for fun. @TaW – Robo Maklen Jul 24 '18 at 14:03
  • I don't see how we can give you a "canonical answer" but if you want to keep Windows and C#, WPF can be very fast if used properly (it's using DirectX underneath): https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/wpf-architecture – Simon Mourier Jul 02 '19 at 18:50
  • Even if you have [THIS](https://imgur.com/Y5E91ZQ) available to you, it's always possible to add more and more data until you overwhelm it. But if you do [this one simple thing](https://stackoverflow.com/questions/44829655/how-can-i-plot-more-than-50-000-values-in-a-scatter-chart-saving-computer-resou/44907069#44907069), then the opposite is true: no matter how much data, it's always possible to make it work. – jsanalytics Jul 02 '19 at 21:03

4 Answers4

2

My observations:

While there are many ways you can squeeze every bit of performance from your system to display graphics, I sincerely do not believe you can find your solution from an answer from this question. But you can find many leads.

You have performance problems drawing a simple graph while "modern applications" have no problem rendering thousands of points, so why is that? A game can render more than 60 frames per second in 4K resolution and you can not render a single frame of dummy graphics to a surface.

How do they do that? Well, they cheat optimize.

If you draw not every point, but only meaningful points and fill the rest by curving like @yves-daoust suggested, you will save on some drawing time. This is like how MP3 compresses audio, it simply removes the parts you most likely be unable to hear.

If you enable DoubleBuffering like @tigran suggested, your result will displayed on screen more efficiently, or better you can draw your graph in another thread and then paint that graph instead of redrawing it in every OnPaint.

You can update only relevant parts of the graph by utilizing Invalidate(Rect) method.

You can draw you graph into a bitmap using direct bit manipulation as @yves-daoust (again) suggested, this may greatly improve your performance but you have to implement every function which is crazy.

While Graphics object uses not GDI but GDI+ it is very well optimized for many not-so-complex drawing operations, you can use othe graphics libraries optimized for performance like DirectX and Skia.

My Suggestion: If you insist you should draw everything then get some books about Graphics using C# and spend some quality time with them. If not, then get some low-cost low-size charting library and be done with it.

My situation: I had implemented a simple line drawing algorithm in Pascal 6.0 (DOS times), using BGIs, using interrupts, using direct memory access and using IO ports. After some skimming on code, one can say I'm into BDSM.

Erdogan Kurtur
  • 3,630
  • 21
  • 39
1

The "cool" plot is most probably drawn (filled) using Bezier curves, which are defined by a small number of so-called control points. APIs like System.Drawing are optimized and efficient for such graphics primitives, that require very little function calls.

If your curves aren't smooth, maybe you can discard points without losing detail, but that depends on your data.

A last resort could be to write your own rendering algorithm that takes advantage of your particular data and generates an image by direct pixel access instead of performing graphics calls. Then you blit the image to the display.

This option requires good knowledge of graphical rendering.

  • How would I use "the direct pixel access". Would it be through c# or would it be through assembly? – Robo Maklen Jul 24 '18 at 15:10
  • 1
    @JMaklen: C# is fine, using the LockBits/UnlockBits trick. But this is the easiest part of the problem. –  Jul 24 '18 at 15:36
1

enter image description here

The answer to your question is deceptively simple. Implement the graph with GPU programming! There are several GPU programming library’s such as Alea GPU for .Net. GPU’s are designed to solve asynchronous problems, such as graphical displays. The reason for this is a GPU can use its thousands of threads to do independent tasks at the same time. Programming a GPU is not a trivial exercise due to the amount of threads executing at once, so you might want to rethink implementing your own graphing application from scratch.

Fun Fact: You can use GPU programing to increase the performance of many asynchronous problems, not just graphical problems.

Cabbage Champion
  • 1,193
  • 1
  • 6
  • 21
-2

So if your writing your own (why?) you really need to avoid System.Drawing as it's very slow. The best solutions use DirectX to take advantage of the GPU(s) in the computer and get them to do what they do best. System.Drawing last time I looked only tapped a single CPU core and is very slow, so if you have millions of datapoints it just does not scale.

It's why there are 3rd party solutions as they have a team that did this already. If you are just doing this for fun or self-exploration then fine, but if it's part of a real product you would be hard-pressed to build something better than some of the teams out there. ChartFX is one of the better performing ones I have seen thus far, but I have hardly tried them all and I'm sure there are others just as good perhaps better.

Kelly
  • 6,992
  • 12
  • 59
  • 76