Games development in JavaScript: Canvas vs DOM benchmark

In my last article I described four frameworks used in games’ developing. What differentiate frameworks is the way in which they render graphic. Each framework I mentioned used DOM and CSS, only one enabled the use of Canvas too. But it’s obvious that in time more and more frameworks will work with it – it’s just still a developing standard.
During writing the previous article, I went in for comparing a performance of Canvas and DOM. It’s known that those are two completely different technologies with different capacities. HTML presents data, CSS gives them an appearance, Canvas draws. So I wondered how to compare them since they are so different.
As the result of my observation I decided that that the most important and the hardest thing is to animate many objects simultaneously (eg. missiles, enemies, obstacles). At the outset I strongly simplified a game model to moving squares. Afterwards I was testing different variants achieved with CSS. So I didn’t test anything what wouldn’t be feasible in CSS – it’s clear that Canvas would be better there (I mean such capacities as drawing diagonal lines or polygons).
SVG would be suitable to tested solutions too. But I have already seen performance’s comparisons between SVG and Canvas (Canvas was faster). And adding the third technology would make testing much more difficult. Maybe another time.
Methodology
I wrote two testing methods. One based only on a for loop and one with nested calls setTimeout(). The main advantage of the first method is that in every browser an empty loop executes in the same time (2ms – 3ms for 1000 iterations). The second one is more diverse — 4s in Chrome 5 and 10s in Firefox 3.6 (@Ubuntu). But, as I dreaded, for loop executes without switching context to rendering engine and for the same number of elements it usually (but not always) takes the same time, no matter how big canvas is. In timeouts loop’s case we can’t compare results between browsers. But UI is refreshing and times depend on canvas’ size so I decided that this method is adequate.
Code:
/* FOR LOOP */
var time_start = +new Date();
for (var i = 0; i < times; ++i) {
fn.apply(fn, [i].concat(pre_args));
}
var time_end = +new Date();
after(result_el, time_start, time_end);
/* TIMEOUTS LOOP */
var time_start = +new Date();
var i = 0;
var fn_timeout = function () {
fn.apply(fn, [i].concat(pre_args));
++i;
if (i < times) {
window.setTimeout(fn_timeout, 0);
}
else {
var time_end = +new Date();
after(result_el, time_start, time_end);
}
};
window.setTimeout(fn_timeout, 0);
Test's variants
It goes without saying that the main DOM's weakness is its slowness. Nowadays operations on elements are this part of JavaScript which hogs CPU most. That's why the first variant is working on a big amount of elements. But changing styles was the only operation I made - I didn't select or insert any elements. About Canvas we know that it doesn't like big canvas. It seems less important for DOM. So five test's variants came into being:
- a small canvas (200x200) and many (200) elements
- a small canvas and few (10) elements
- a big canvas (800x600) and plenty (500) of elements
- a big canvas and many elements
- a big canvas and few elements
Tested properties
I've started with testing movement. But position isn't the only property which we animate, so I've made the list of properties I wanted to test:
- position (top, left)
- color (rgba)
- rotation (as an advanced CSS feature)
- background image position (for css) and image cropping (for Canvas) for testing sprite based animations
- color and rotation (for fun — isn't it psychedelic?
Tests
- Empty function (no elements' changes): variant 1, variant 2, variant 3, variant 4, varaint 5
- Position: variant 1, variant 2, variant 3, variant 4, variant 5
- Color: variant 1, variant 2, variant 3, variant 4, variant 5
- Rotation: variant 1, variant 2, variant 3, variant 4, variant 5
- Sprites: variant 1., variant 2., variant 3., variant 4., variant 5.
- Rotation and color: variant 1., variant 2., variant 3., variant 4., variant 5.
I've carried out this test in Chrome 5.0.3 and Firefox 3.6.2 (both runnig on Ubuntu). See results on Google Docs. I've marked in green times which are at least 10% better in each pair.
Conculsions
In brief — Canvas likes small size of canvas and DOM likes working with few elements (although DOM in Firefox is so slow that it's not always true).
I think that a thorough analysis of the results I have to leave to people concerned. However, I have a few interesting observations (not always obvious):
- Chrome is 2-4 times faster than Firefox. Canvas in case of empty (small amount of elements) but large size canvas is an exception.
- DOM likes a small number of operations on elements (in each frame), simple properties (position, background position, background color) and works fine with large size canvas too.
- Canvas coupes better with many changes of properties (because there are no objects) and with rendering of advanced transformations (rotation). Unfortunately it doesn't like refreshing large size canvas.
- Results for DOM in Firefox are independent from the size of canvas. Except for rotation, which is up to 5 times slower in case of large size canvas.
- In Chrome size of canvas is significant for DOM too (strange).
- In Chrome results are clear: a lot of elements — DOM loses, large canvas size — Canvas loses.
- In Firefox Canvas wins in case of small size of canvas and large number of elements. However DOM is so (extremely) slow that its advantages sometimes aren't observable.
- Canvas in Chrome in case of small number of elements is more sensitive for size of canvas than in Firefox.
More
I've made detailed comparison of Canvas' and DOM's performance. If you're interested how these technologies make out in comparison with Flash and SVG, see "HTML5" versus Flash: Animation Benchmarking. Flash still wins.
We need a hardware support now!
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
March 30, 2010 in Games, JavaScript, Programming | View Comments
-
MeanEYE
-
Elsamuko
-
George







