Performance problems with HTML5 Canvas in some mobile browsers.

wirrbel picture wirrbel · Apr 24, 2013 · Viewed 23.7k times · Source

Hi I have a Webapp that should be able to run on both Smartphone and Desktop Browsers alike. While I was expecting to get some curious behaviour on small devices like the Iphone, I was pretty confident that it would run well on an Android Galaxy Tab which is the Android Device that I can run tests with at the moment.

Now I have installed a bunch of Browsers on the Galaxy Tab to test things with:

  • Android Native Browser
  • Chrome for Android
  • Firefox for Android

On the Desktop I have used

  • Firefox
  • Google Chrome

and finally I have an Iphone to test with.

The website uses HTML5 canvas for pixel and sprite based drawing no fancy transformation, filters or effects, mostly simple paths and polygons. I do listen to touch events and use requestAnimationFrame for proper redrawing.

Overall the application runs well on Desktop Browsers, it is also running great on iOS Safari (iPhone) and Firefox-on-Android. Yet Androids Native Browser is giving me trouble. I have set it up so that the screen flushes red when the javascript is not responsive, and it does flash almost always when touching the screen.

So I wonder whether there are any known issues with Android Native App and HTML5. Due to the nonexistent Name of the native Browser its quite hard to google information about this. Any ideas for me where I can get more information? Any ideas what might cause the lagging of the native Android browser?

There are a few ideas about the issue:

  • iOS does not support requestAnimationFrame, therefore I replaced it with a timeout based replacement. If I use that replacement on Android's native browser, the problem persists.

  • I use AJAX (google clojure xhrio) quite regularly to retrieve data from the server. Could it be that data retrieval callbacks are cloggin my event pipeline?

  • Are log console messages (console.log) known to slow down applications? Could they trigger the browser to rerun through the DOM tree or anything related?

Answer

Gustavo Carvalho picture Gustavo Carvalho · Apr 25, 2013

I've done a lot of experiments with canvas in many browsers. Some performance issues that I noticed:

First, about your guessing:

  • When requestAnimationFrame is supported by a browser, the drawing stuff and the app itself are more responsive. Use setTimeout or setInterval as a fallback are always possible but you need to be careful about the timing. This robust polyfill may help a little, but nothing compared to native requestAnimationFrame.

  • If console.log is called every frame (or almost), yes the performance goes down. Since native Android Browser doesn't have a console Object, every time it is called will generate an error that also contributes to slow down your application. You can do this:

    if(typeof console === "undefined"){ console = {}; }

  • For intense real-time applications web sockets are faster then http requests. Unfortunately this feature is not supported by old native android browsers. If it's not possible to use web sockets, you should minimize the http requests.

Note: Chrome for android support most of HTML5 features cited here, including requestAnimationFrame and websockets.

More information:

  • Drawing text using the context 2d fillText it's too expensive, but in some browsers this is even worse. Pre-render your texts in another canvas or use bitmap fonts. (In native Android Browser, after replace filltext drawing for pre-render stuff, the performance grew from 10-15 FPS to 30-45 FPS in some games I've made).

  • Avoid scale and rotate context because they also cause drop down in performance. If you need to scale or rotate a sprite only once, use pre-render either.

  • You need to minimize the real time drawing. Pre-render your stuff whenever you can. Redraw only stuff that changed and needs to be updated.

  • Try to write memory efficient and garbage collector friendly code.

There are a lot more things to do. I just cited a few.

TIP: make some stress tests for features you don't sure if they are performance killers and capture the benchmark results.

In mobile applications, specially real time apps, all optimizations are welcome no mater if it's just an over optimization or a bit of memory gain.

For more information follow the links below:

Also search for performance in Posts & Tutorials.

EDIT
This jsfiddle code snippet shows some stuff covered in this answer and provides a rough fps counter to benchmark. Edit this fiddle by yourself and check it out.