Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance Improvement using ImageData #175

Open
ifsarbaby opened this issue Jun 8, 2020 · 10 comments
Open

Performance Improvement using ImageData #175

ifsarbaby opened this issue Jun 8, 2020 · 10 comments

Comments

@ifsarbaby
Copy link

Hi SWTChart team,

First, I want to say thank you for making such a great charting library. I'm a long time SWT developer and I'm glad to see that cool tools such as this are still being developed.

In my current application I am plotting large amounts of data (30,000 points) as line charts or scatter plots. I would like to refresh the plots quickly. I noticed that the performance of scatter plots was very slow. Specifically it would take 2.5s to render 30000 points (without compression). Looking at how LineSeries data was plotted and doing profiling of the source code, the GC drawing methods are very expensive to draw a symbol and and accounted for the vast majority of the render time. (There are some other potential savings that I see in the code, but nothing close to the time spent calling the GC methods)

To solve this, I modified the LineSeries code and cloned the functionality to draw directly on an imagedata object by setting the pixels required. I made a second version of many of the LineSeries functions (like drawLineAndArea) that use an ImageData directly instead of GC. After rendering to the ImageData, A single GC.drawImage is required to draw the points over the background chart.

The resulting performance is ~2ms to plot the same points. This is a 1000x increase and allows me to plot the data as it arrives in the system in a "real-time" display. Out of the 2ms, most of the time (80%) is the gc.drawImage. For multiple line series on the same chart, I can resuse the ImageData making the incremental rendering of layers 5000x faster than before.

Similarly, I can improve the line rendering slightly (by a factor of 3-4x only) by drawing lines directly on the ImageData using a Bresenham line algorithm. (the GC.drawline method is reasonably efficient vs self created one, with only a 3-4x performance difference)

I would very much like to see a Performance increase of this powerful SWT library. I offer up the code that I modified, if it is useful to this team. It is not production ready, but could be completed and integrated with someone who has higher knowledge of the library than myself. I myself, do not have much time that I can offer to support this tool development.

Please let me know if it is of use, and I can package it up.

Thanks,

@eselmeister
Copy link
Contributor

@ifsarbaby Yep, we are working steadily to improve the plotting performance. An optimization has been recently added to speed up the selection process by creating an image of the chart and setting it in the background as long as the selection process lasts:

#85

We would be highly interested in your solution. Due to compatibility reasons, code needs to be tested and validated on several OS. We often see, that minor problems occur on macOS and GTK3.

It would be great if you could share your code with some explanations. We could then inspect it and probably merge it into the SWTChart code base.

@ifsarbaby
Copy link
Author

Hi,
Sorry for the delay in this, I had other items I needed to address. I wanted to clean up the code and do some more testing before I pass this on. I also improved the algorithm further, and included clipping (i.e. never render a pixel outside of the visible area) to furthur improve performance. The solution that I came up with is really quite fast, and I am happy that we can plot data in real-time. I am refreshing data in multiple plots at 30Hz (50,000 points) and it is buttery smooth.

Please find attached the following, with some explanation of what I did:

  • PlotArea.java - modified to use the new methods added to LineSeries
  • LineSeries.java - added new methods to paint using ImageData (instead of GC). I preserved the original methods, and only added new methods
  • ChartLayout.java - I modifed Chartlayout to include an option (setAdjustForMostLeftRightTickLabel()) that disables calling adjustForMostLeftRightTickLabel(). When this is enabled, the location of the plot area can change based on the axis labels, and that creates a sometimes jittery graph if you are doing real-time plotting.
  • FastLineDrawingSWT - A custom line drawing algorithm that uses ImageData. Currently supports lines and symbols, however it has some limitations: No line styles (just width and color is supported), and only square symbols. However this could be added on at some point.

The FastLineDrawingSWT methods can be extended to work directly on a bitmap, and could integrate nicely with what you mentioned. I actually turn compression off, on my datasource, as it is faster that with it. The LineSeries.drawLine() method checks if the X and Y already maps to the same pixel coordinate as the previous and therefore will skip it. So it's more of an "on the fly" compression that compressing the data first.

Let me know if I can be of any further help.

SWTChart_Performance.zip

cheers,

@eselmeister
Copy link
Contributor

eselmeister commented Aug 20, 2020 via email

@ifsarbaby
Copy link
Author

Gruesse Eselmeister

Regarding your questions:

  • The code for FastLineDrawingSWT is my own code.
  • I have not tested this on mac or linux, however I would anticipate no problems. The algorithm uses java methods and not any SWT system OS calls that are known to cause problems.

I have completed the eclipse contributors agreement as provided. However, I don't have time to contribute anything more than what I provided at this time -- I am only passing on the solution in hopes that someone else can take it further that understands the mechanics of this library.

I do agree with the approach of having the user select the plotting method. That would be logical, and allow for the new algorithm to be used, even with limited features. I'll take a look at the buffered section.

Cheers,

@eselmeister
Copy link
Contributor

eselmeister commented Aug 24, 2020 via email

@buchen
Copy link
Contributor

buchen commented Oct 25, 2024

Did this contribution in made it into the code base?

I am asking because the performance of the line charts make me hesitate to move from org.swtchart to org.eclipse.swtchart because the tooltips are visibly jerky ("ruckeln"). I don't really understand what the difference is, but there appears to be a paint event when re-positioning the tooltip. And that paint event is relative slow. I am wondering if such a change as this could help.

@eselmeister
Copy link
Contributor

Unfortunately, the code didn't make it into the code base as @ifsarbaby didn't create an official pull request.

@eselmeister
Copy link
Contributor

It would be great to speed up the plotting even when using a huge amount of data points.

@eselmeister
Copy link
Contributor

@buchen I will inspect the requested changes and try to create a PR to make the charts faster.

@buchen
Copy link
Contributor

buchen commented Oct 27, 2024

@eselmeister thanks. After some more investigation, I believe at the moment that the primary problem are additional paint events. This change could make the drawing faster, but I wonder why the paint events occur in the first place: #420

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants