Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Poor Canvas2D performance with Firefox on Linux

I just hit something particularly hard to debug when doing some pretty intensive rendering with Canvas2D. I use all kinds of things, from globalCompositeOperation to multiple off-screen canvases, with some drawImage magic in-between.

It works perfectly fine and smooth on :

  • Chrome (26) [OSX 10.7.5]
  • Safari (6.0.2) [OSX 10.7.5]
  • Firefox (Both 18 and 20 Aurora) [OSX 10.7.5]
  • Chrome (24) [Windows 7]
  • Firefox (12) [Windows 7]
  • Chromium (24) [Archlinux, Gnome 3]

EDIT: Added tests for Windows 7. Strangely enough, it works for FF12 (I had an old version on my dual boot) but there's a definite performance hit after upgrading to FF18. It's not as bad on Windows as it is on Linux though, and the same version on OSX works flawlessly. Regression maybe?

For some reason, on Firefox and Linux (I tried both 18 and 20 Aurora), I have bad rendering performances when dragging and rendering at the same time.

If I fire-and-forget an animation, it is on par with Chrome/Safari, but if I drag and render, I often end up only seeing the end frame after I release the drag.

  • Neither requestAnimationFrame nor a direct rendering on the mouse event handler work.
  • After profiling, the reported timings for the rendering parts are well within the range of acceptable (up to 100ms at the absolute worst), and definitely do not correspond to what I see on the screen.
  • I tried reducing the load by removing some stuff, ending up with reported render times under 15ms, but what I saw didn't change.

What baffles me is that it works almost everywhere else except with Firefox on Linux. Any idea as to where I should look, a bug report or a solution to my problem?

like image 617
F.X. Avatar asked Oct 05 '22 06:10

F.X.


2 Answers

I have fully switched to Chrome on linux because of this issue. It stems from the old 2d rendering engine they are using called Cairo, which is old and out-dated. Azure was to replace this engine and they have it done basically all the platforms except linux.

http://blog.mozilla.org/joe/2011/04/26/introducing-the-azure-project/ https://bugzilla.mozilla.org/show_bug.cgi?id=781731

like image 132
Atherion Avatar answered Oct 12 '22 19:10

Atherion


I think I know where you should look based on this:

If I fire-and-forget an animation, it is on par with Chrome/Safari, but if I drag and render, I often end up only seeing the end frame after I release the drag.

This is probably a double-buffering bug with Firefox on linux.

Canvas implementations have double-buffering built in. You can see it in action on any browser in a simple example like this one: http://jsfiddle.net/simonsarris/XzAjv/ (which uses a setTimeout vs extra work to illustrate that clearing does not happen right away)

The implementations try to delay all rendering by rendering it to an internal bitmap, and then all at once (at the next pause) render it to the canvas. This stops the "flickering" effect when clearing a canvas before redrawing a scene, which is good.

But it seems there's a plain old bug in the Linux Firefox. During your drag and render it seems to not be updating the canvas, probably in an attempt to buffer, but seems to be doing so when it should not be. This would explain why it works in fire-and-forget scenarios.


So I think a bug report is in order. I haven't got any linux machines lying around so I can't reproduce it and submit something myself to be certain though, sorry.


This is in reply to a comment: You could, during the mouse move, dispatch the drawing portion to a tiny timer.

For instance:

// The old way
theCanvas.addEventListener('mousemove', function() {
  // if we're dragging and are redrawing
  drawingCode();
}, false);

// The new way
theCanvas.addEventListener('mousemove', function() {
  // if we're dragging and are redrawing

  // in 1 millisecond, fire off drawing code
  setTimeout(function() { drawingCode(); }, 1);
}, false);

There isn't such a method, its totally hidden. What you could do is, during mouse move, dispatch

like image 30
Simon Sarris Avatar answered Oct 12 '22 19:10

Simon Sarris