Use DrawPolyLine instead of Drawline for linechart
Status: Beta
Brought to you by:
yoshitaka
Hi,
In SWTChart the drawLine method in http://sourceforge.net/p/swt-chart/code/300/tree/trunk/org.swtchart/src/org/swtchart/internal/series/LineSeries.java#l520 uses drawline instead of drawPolyLine. The problem with this is when you have 1 point per pixel:
1- it slows down tremendously as a series needs to pumps twice as many vertices,
2- the style is reset, so everything becomes a solid line.
Would a fix be possible?
Thanks, and I love your work!
Matthew
I did some testing:
with the following code, polylines are 5x faster and diplay styles properly.
Last edit: Matthew Khouzam 2014-02-04
Hi Matthew,
Thanks for your feedback.
I believe it is the right direction to use drawPolyline(), but some investigation is needed.
There are two things to take into account.
1) In LineSeires.drawLine(), vertical lines and slope lines are drawn separately, and they are not always connected. In order to use drawPolyline(), additional line segments are required in order to connect each other.
2) Using drawPolyline() is 5x faster than drawLine() with your attached code, but it is only 2x faster if setting line width to non-zero value on Windows.
I have to check how to create a polyline without causing performance degradation (i.e. less than 2x vertices). Also, memory consumption has to be checked, when instantiating polyline array dynamically for each new view port.
Best Regards,
Yoshitaka
I've modified lineseries as a test, this may help things out.
On Wed, Feb 5, 2014 at 11:47 AM, yoshitaka yoshitaka@users.sf.net wrote:
--
Matthew Khouzam, Human Being
Related
Bugs:
#36Depending on line width and y series values, performance is much different. For example, with the attached code (DrawPolyline.java), drawPolyline is 100x slower than drawLine.
Since SWTChart should support handling arbitrary y series, the attached code (DrawingPerformance.java) should also work with reasonable performance, but doesn't show good result as below in my environment.
Case 1) as is
=> 30 ms
Case 2) replaced drawLine with drawPolyline: (LineSeries.java.case2)
=> 40000 ms
Case 3) replaced drawLine with drawPolyline with optimization: (LineSeries.java.case3)
=> 6000 ms
Further investigation is needed (considering the way to switch the drawing method depending on given series and configuration).
That is interesting, did drawline show the styles? That was the main issue,
the performance was a theoretical bonus. :)
Our first issue was that lineseries with too many points (let's say spaced
a pixel apart, the lines are not "dashdots" but rather solid. Polyline
appears to be well displayed.
On Fri, Feb 7, 2014 at 11:49 AM, yoshitaka yoshitaka@users.sf.net wrote:
--
Matthew Khouzam, Human Being
Related
Bugs:
#36Hi Yoshitaka,
I got your drawingperformance test up and running, I just need to fin where the draw function is that will be called by the profiler. Could you please point me to it.
Also, I see why it works here:
a- the random seed is not set, so the test results are not super reproductible.
b- The swing is so big that the line style is maintained in that example.
c- you tested with more points than we have pixels. This is an interesting case. I will look into it more. :)
Thanks for your super fast help! :)
Matt
To workaround the bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=243588 on Windows, GC.setAdvanced(true) would be called before drawing polyline. Until that bug is fixed, original code calling drawLine() would be still used when line style is not set, in order to minimize the risk of side effect.
So I am using linux, I didn't experience that bug, and am now curious if mac has a third behaviour. I tested this thouroughly imo using the sin wave and growing point samples, these results are only on my machine:
points, window resolution, acceleration from drawline to polyline, are styles well displayed in drawline?, polyline?
10, 500x400, 0.75 , no, yes
10, 1920x1200, 0.6 , no, yes
100, 500x400, 1.5 , no, yes
100, 1920x1200, 2 , no, yes
1000, 500x400, 4.2 , no, yes
1000, 1920x1200, 4.1 , no, yes
5000, 500x400, 5.4 , no, yes
5000, 1920x1200, 20 , no, yes
10000, 500x400, 8 , no, yes
10000, 1920x1200, 8 , no, yes
50000, 500x400, 174 , no, yes
50000, 1920x1200, 12 , no, yes
please take a look at this patch if you wish to reproduce the results. Run the test called LineChartBenchmarkExample located in org.swtchart.examples
Hi Matthew,
The attached file (LineSeries.java) has the changes to switch the drawing method depending on whether line style is set. That is, if line style is set, drawPolyline() is used with workaround of setting ‘advanced’, otherwise drawLine() is used as it is today. From functionality point of view, that idea should be ok, but the performance looks not very good. The way of creating polyline is not optimal. Especially when there is vertical line in every pixel, there is around 50% redundancy. Your optimization looks interesting, but I have seen some cases where line is not correctly drawn (reproducible with Example.java). I will spend some additional effort to look for better optimization, but if not found, I would take the attached code as solution for now. Any other idea or feedback is welcome. Thanks.
Best Regards,
Yoshitaka
This patch looks very good to me, it solves our immediate issue here.
Thanks!
ps. as for the optimisation, and this will be at a later time, I see 3 easy optimisations:
1- avoid boxing/unboxing, so always staying int, that means ditching lists. :(
2- removing consecutive points that overlap. this irl will save in some cases here 90-99% of the points to draw.
3- removing middle points that are aligned. This I found in my tests save 5-10% of points but requires more code to check and you have to deal with all the div by 0.