I was expecting to find Safari the fastest, Chrome the slowest, and FireFox just a bit quicker than Chrome because this is what
I find if I render a graph with D3 in this app I am working on:
http://stepheneb.github.com/avalanche2d-js/avalanche2d.html
I was hoping to have a simple test case for creating a performance issue for Chrome and FireFox ... but ...
this is what I measure as the time to add line segments 4750..5000:
Safari v5.1.1 (6534.51.22) 77ms
Chrome v14.0.835.186 86ms
FireFox 7.0.1 3407ms
I must be doing something wrong ... FF is not that slow ... any pointers would be appreciated.
One clue is that I am using requestAnimFrame to schedule the work ... but the SVG path and the results rows in the table don't
appear until after everything is finished -- so I'm probably using it wrong.
fyi: You won't see the table results in the latest Chrome Canary because of this recent bug:
Regression: SVG in IFrame uses maximum height of container instead of specified dimensions.
http://code.google.com/p/chromium/issues/detail?id=98951
Here's the equivalent benchmark for drawing a line consisting of 5000 separate segments into an HTML5 Canvas -- it's about 40x faster than drawing with SVG.
I knew drawing with an HTML5 Canvas was faster but didn't realize it was this much faster than SVG.
I wouldn't say that's true in general: performance is typically
comparable, and often SVG is faster if you are performing incremental
modifications vs. a naïve full redraw with Canvas. But, it seems true
in this case where you're just incrementally adding geometry. Drawing
n path segments on top of m existing path segments in Canvas costs
O(n) rather than O(n+m) with SVG.
Mike
So far the main places where I think Canvas is better are:
1) Larger heatmaps.
Example: left side here: http://stepheneb.github.com/avalanche2d-js/avalanche2d.html, a 100x100 cell heat map.
2) Faster real-time graphing of large datasets
Example: right side here: http://stepheneb.github.com/avalanche2d-js/avalanche2d.html after several thousand points are collected and rendered.
Of course there's nothing that prevents me combining SVG and Canvas together.
In the avalanche-js demo I could overlay a transparent canvas object over the inner portion of the DS.js graph and plot using Canvas while collecting data.
I could still rescale the axes by dragging the D3 generated SVG axes while plotting and replot the entire 5000 point dataset using Canvas in about 30ms.
I could also draw the complete line in D3 after data generation/collection stopped to enable more interactive introspectionof the graph visualization.
A hybrid approach like you describe would be nifty.
-bewest
On Wed, Oct 19, 2011 at 10:22 AM, Stephen Bannasch
<stephen....@deanbrook.org> wrote:
> At 12:17 AM -0400 10/19/11, Mike Bostock wrote:
It is nifty and it's working well.
I'm now using the Canvas over D3/SVG hybrid approach when plotting fast real-time data streams.
When not plotting an active real-time data stream what you see is all D3/SVG.
However Canvas is so fast re-plotting a 20,000 point line segment that for now I haven't even disabled updating the Canvas rendering when I place the Canvas layer beneath the SVG layers when the real-time data stream is stopped.
I just updated avalanche2d-js so that the graph drawn into the canvas overlay during real-time data collection re-scales properly when the axes are changed while graphing.
http://stepheneb.github.com/avalanche2d-js/avalanche2d.html
Because of how D3 is designed this was quite easy.
update real-time canvas graph when scales change
https://github.com/stepheneb/avalanche2d-js/commit/32c826955575
In my experience, Firefox is slow not because of SVG rendering, but because it's DOM engine is slow. Firefox just chokes on too many elements.
Because of that, I also arrived at a hybrid canvas/svg approach which has worked well. But I discovered a critical bug that occurs in Safari browsers only on Lion or iOS5 with regard to canvas rendering when embedded in SVG. Seems that in the switch from Webkit1 to Webkit2 (only on Lion or iOS5) they broke a bunch of things with regard to SVG, including any transforms on canvas.
I think this is the relevant bug: https://bugs.webkit.org/show_bug.cgi?id=68635
Right.
My dom starts with:
<div id-"chart"></div>
After D3 starts up it looks like:
<div id-"chart">
<svg>...</svg>
</div>
And after I add my Canvas overlay it looks like this:
<div id-"chart">
<svg>...</svg>
<canvas></canvas>
</div>