2

I wrote a processing.js visualization for displaying pair-wise information as a triangle-plot/heatmap.

triangle plot

Here is a working jsfiddle version: http://jsfiddle.net/timeu/uK6SB/

Performance is somehow fine, however I think there might be some room for improvement.

Basically in the above example I display 691 pair-wise information (477481 float values between 0 and 1) as a heatmap.
As I am only interested in a certain range so I only color-code values above a certain threshold (0.3 in my case).
After filtering I end up with approximately 10 000 float values for which I have to display colored rectangles.
When the user moves the mouse over a datapoint it will grey out all values and only highlight the selected one and display the pair-wise value in the scaler on the left side.

The plot is created using following steps:

  1. Create a rectangle with a blue background (for all values below the threshold)
  2. Create colored rectangles for all values above the threshold (around 10.000)
  3. Rotate and translate the screen to create the triangle effect

When the user moves the mouse above a datapoint it does following steps in additional to the above ones:

  1. Draw a half transparent grey rectangle over the whole plot (to grey out all other values)
  2. Redraw the datapoint

In my first naive approach I redraw the whole plot when I the highlighted datapoint is changed. However performance was really bad. After profiling I found out that redrawing 10.000 rectangles is the bottleneck.
To fix this I draw the initial plot once into a backbuffer (in processing.js one can use a PImage) and then just re-draw the backbuffer when I need to update the plot. This significantly improved performance.

However when I display the plot with a really high resolution (above 2000 pixels), performance degrades quite a bit. After profiling I found out that toImageData (re-drawing the backbuffer) takes most of the time.
I did some research on how to improve canvas performance (html5rocks,msdn,stackoverflow)

So I came up with following possible improvements:

  • As I only display a maximum of 500 points (-> 250.000 float values) I could just render my plot with a resolution of 500x500 px and then use hardware upscaling to upscale to the native resolution.
  • I calculate the size of the rectangle by dividing the width of the canvas by the number of points. Most of the time I end up with floating point coordinates which lead to subpixel rendering and bad performance. However rounding is not an option as I have the requirement to use up all the available space (if I round up I won't see the complete plot and if I floor the coordinates the plot doesn't span the entire canvas). Is there a solution?
  • Instead of redrawing the whole backbuffer when I highlight a different datapoint I could somehow use clearRect and redraw the parts that have changed. Not sure how exactly this can be done tough.

I would be thankful for any feedback or additional performance suggestions.

4

0 に答える 0