PaintWeb performance
28 May 2009, 11:55
Hello everyone!
This week I have completed my work on performance testing and improvements for PaintWeb on the OLPC XO laptop.
During testing it became obvious that something other than the actual Canvas painting was very slow on the XO. The main performance culprit is that the default Gecko-based browser is configured to render pages using 134 DPI instead of the default 96 DPI. Generally web browsers render pages using 96 DPI. If the XO web browser would do the same the texts and the images would be far too small - the XO display is an odd 200 DPI screen perceived as 134 DPI.
PaintWeb's drawing performance was hugely affected by the bilinear scaling of the Canvas elements being done by the browser on the XO. When I configured the browser to render the page using 96 DPI, the web application became a lot more responsive.
Martin Langhoff, my mentor, got in contact with Robert O'Callahan from Mozilla. He provided us with lots of help in finding a solution for the performance issue.
We did think about having a CSS property to change the DPI only for the Canvas elements, or a different CSS property to disable scaling, or some proprietary API for changing the DPI on a single page. None of these are good ideas, because they allow web developers to start coding for specific DPIs - this is not desired.
Gecko scales pages using integer scaling factors - that's 1, 2, 3, etc - it doesn't use floating point numbers. In a normal Gecko build the scaling factor for 134 DPI is 1 - because 134 / 96 = 1, so you do not get any scaling. You can have a scaling factor of 2 or higher if you go above 192 DPI.
Gecko is patched on the XO in a way that it forces the browser to scale pages using floating-point scaling factors as well. Therefore, for 134 DPI the pages are scaled and they look really good on the XO screen.
The final solution which I implemented into PaintWeb is to simply scale down the Canvas elements in my document. If I accurately scale down the elements, Gecko is sufficiently optimized to cancel any scaling and you do not notice any performance impact. This works really great.
In Gecko 1.9.1 (Firefox 3.5) I can detect the DPI used for rendering the page with CSS 3 Media Queries. I use this in PaintWeb. However, the XO only has Gecko 1.9.0 for now, so I cannot determine the DPI. I am forced to do user agent sniffing to check if the browser runs on the OLPC XO. If it does, then I scale down the Canvas elements using a different way of calculating the scale-down factor - because Gecko is patched - and I always consider the page is render using 134 DPI. Fun, huh? ;)
On Opera, on the XO, I did all my testing using 100% zoom level. It ran much better than Gecko, for obvious reasons (no scaling, yay). Once I fixed the Gecko scaling issue, Opera came second. For some reason Canvas draws much faster in Gecko than in Opera on the OLPC XO.
Opera cannot render pages using different DPI values other than 96. People use zoom, so, for consistency, I use an old trick to measure the zoom level (thanks Arve). Based on this I scale down the Canvas elements. For some zoom levels, like 200%, the scaling is cancelled and PaintWeb works better. Unfortunately, Opera does not allow non-integer pixel values, thus the scaling-down is generally not effective...
Another important performance improvement in PaintWeb is the use of timer-based canvas drawing. This means that mouse move events are either cancelled or coalesced into one. For example, redrawing a polygon with a lot of points for every mouse move is very slow. The tools in PaintWeb use timers to update the canvas every few milliseconds. This approach makes PaintWeb feel faster.
Lastly, I now avoid going into the global scope, for things like
Math.round
or such. The importance of this change is reduced by the fact the JavaScript that runs is not very
intensive - not too much code is executed for each mouse move event. Such changes become more important the more code you
run. This will be important for the color space visualization I have.
The loading performance will improve greatly once I will make a packager for PaintWeb. Additionally, I will continue to constantly check the overall performance of the web application on the OLPC XO.
Go ahead and try PaintWeb from SVN trunk. Lots of thanks to Robert for his great help and to Martin for his assistance and for finding the Gecko patches.
Currently I am working on the new user interface, stay tuned!
Update May 31, 2009: Just published a page on the OLPC wiki about the HTML Canvas performance on the OLPC XO laptops. The page includes code snippets explaining how to work-around the scaling issue.