The first call takes 124 ms (!) while the next one takes only 1 ms. To put that into perspective, it means that drawing** 10 sprites** would take more than one second. And this is for a single frame!
Some kind of conversion (texture ? color format ?) must happen when first using the enemy sprites canvas (that was converted from an image first).
I decided to use the enemy canvas once to draw random data before triggering the enemy wave. If was right, the first draw call would then be as fast as the next ones.
Again, the results confirm what I thought:
I have accessed the sprite canvas and wrote it onto the game’s canvas before triggering the enemy wave: as you can see, the first call now takes 0 ms!
I’m currently focused on optimizing performance for the desktop but from time to time, I test the engine on mobile devices: this helps me fixing bottlenecks and optimizing the engine where it is the slower.
Since I do not own Apple iOS device, I first tested the engine on Android devices: on my 2-year old Nexus 4, the performance seemed to be acceptable but I noticed one thing:** performance varies a lot across the different browsers**.
Canvas rendering** is a lot faster on Firefox** than it is on Chrome: I reach about 30 fps on Firefox where Chrome barely reaches 20 fps: Firefox is 50% faster than Chrome in this particular case.
I then borrowed a friend’s iPad and Safari simply crashed when starting the game: I really wasn’t expecting this!
Since I do not own a Mac, debugging was a pain in the ass and I felt like I was back 10 years in the past when calling alert() was the only way to debug. I first fixed some bugs: my engine was drawing more tiles than needed so the target position was out of the canvas. This shouldn’t crash, but we never know. And… nothing: the crash was still there :(
I then tried to draw less tiles than needed so I only drew a single line of tiles: it seemed to fix the problem, but after testing on another iOS device, the crash was back, so it had nothing to do with the number of tiles and the crash seemed to appear randomly, depending on the device.
I really didn’t know what to do and was about to give up when I recalled I was caching the images I was using for the sprites into a canvas, and then was using that canvas to draw onto the engine’s canvas. There was no apparent reason why this should be the problem, but well… Desperate times call for desperate mesures ;)
So I removed the cache and drew directly from the sprites Image element onto the engine’s canvas and… Voila! It worked!
For some obscure reason, drawing from the cached canvas doesn’t work and crashes on Safari: maybe the image is too big (it’s about 2000 pixel wide), I haven’t tracked the exact problem. I also wanted to submit a bug to Apple but didn’t find a way to do that: submiting a bug seems to require a developer account.
Anyway, this was worth the trouble: the performance on iOS is excellent and 60 fps are reached on a rather old iPad Mini!
So it seems Apple really did a good work at optimising canvas rendering when compared to Android. But at the expense of some bugs ;)
Update: the crash has been fixed in iOS9, thanks to @CuriouslyChris.