

Improving HTML5 Canvas Performance - pooriaazimi
http://www.html5rocks.com/en/tutorials/canvas/performance/

======
simonsarris
Hey I was featured in this! :D

I was asked to help write it, but few of my collected performance notes made
it into the article because I was too slow. On the plus side, I'll have a
canvas performance chapter out in two books in the near future.

Here are a couple off the top of my head really quick:

* pre-rendering is most applicable to text, especially text that never moves (Such as buttons). In fact, any text or complex paths+text to make things like buttons should be turned into pngs. Drawing text and changing fonts is extremely slow.

* re-use your gradients as much as possible, and try to avoid creating them in loops. If you have one gradient that fills several figures you should be making it only once. The function createLinearGradient(x0, y0, x1, y1) goes from one point to another, but you can make your gradient at the origin createLinearGradient(0, 0, toX, toY) and then _translate_ it into the correct location for each figure made in the for loop.

* cache cache cache canvas properties. Never ever set any of them more than you have to, `font` especially. The setter for `font` and the fill styles can change the value so setting it to the same value twice might not be a no-op. It's up to you to make it so. And setting the font especially is really, really slow.

* Avoid save and restore, use them rarely if ever. The only time you should ever really need them is because there is no resetClip currently implemented. For transforms you can can track of them yourself, here's a simple file I made to do that:

[https://github.com/simonsarris/Canvas-
tutorials/blob/master/...](https://github.com/simonsarris/Canvas-
tutorials/blob/master/transform.js)

* fillRect(x,y,1,1) will always be faster than 1x1 putImageData(x,y), but 400 fillRect's will be slower than a 20x20 putImageData(x,y). How often the fillStyle changes will change that hand-wavy metric of mine. If you're placing a lot of pixels in a single frame you should definitely test both to see which is faster in your scenario.

~~~
p0nce
> re-use your gradients as much as possible, and try to avoid creating them in
> loops. If you have one gradient that fills several figures you should be
> making it only once. The function createLinearGradient(x0, y0, x1, y1) goes
> from one point to another, but you can make your gradient at the origin
> createLinearGradient(0, 0, toX, toY) and then translate it into the correct
> location for each figure made in the for loop.

Very true, I did exactly that for <http://www.gamesfrommars.fr/demojsv2/>

------
randallu
It would be interesting to see these run against a "null" canvas backend to
understand how much of the time is JS dispatch versus draw. Also, I think
recent Chromium doesn't perform the drawing directly, but records the commands
and plays them back in another process, so I'd expect any readback operations
(where JS sees the raw pixels) to be slow.

------
dbaupp
Why is this using such an old version of Firefox? (3 version back now, 2 when
it was published.)

(This is a serious question, the author seems to have a lot of up-to-date
browsers, except for FF, so presumably there is some explanation, e.g.
updating process is too difficult, or something.)

~~~
azakai
The article is over a year old, so all browsers there are older.

~~~
dbaupp
Woah! Completely missed that it was published in August _2011_ , not 2012.
Thanks!

