Using PC Hardware more efficiently in HTML5: New Web Performance APIs, Part 1

Browsers need amazing performance to deliver on the promise of HTML5 applications. Web developers need API’s to efficiently take advantage of modern PC hardware through HTML5 and build high performance Web applications with efficient power use for great, all around customer experiences. The second IE10 Platform Preview supports three emerging API’s from the W3C Web Performance Working Group which enable developers to make the most of the underlying hardware and use battery power more efficiently: requestAnimationFrame, Page Visibility and setImmediate.

Together with Google, Mozilla, and others on the W3C Web Performance Working Group and the community, we designed these new API’s over the last three months. These three API’s are a great example of how quickly new ideas can become interoperable standards developers can depend on in modern HTML5 enabled browsers.

This post details how to use the requestAnimationFrame API for better performance and power efficiency.

requestAnimationFrame API: like setTimeout, but with less wasted effort

Web developers can now schedule animations to reduce power consumption and choppiness. For example, animations today generally occur even when a Web site is in a background tab, minimized, or otherwise not visible, wasting precious battery life. Animations today are not generally aligned with the display’s refresh rate, causing choppiness in the animation. Until the requestAnimationFrame API, the Web platform did not provide an efficient means for Web developers to schedule graphics timers for animations.

Let’s take a look at an example. Most animations use a JavaScript timer resolution of less than 16.7ms to draw animations, even though most monitors can only display at 16.7ms periods (at 60Hz frequency). The first graph below represents the 16.7ms display monitor frequency. The second graph represents a typical setTimout or setInterval of 10ms. In this case, the consumer will never see every third draw because another draw will occur before the display refreshes. This overdrawing results in choppy animations as every third frame is being lost. Reducing the timer resolution can also negatively impact battery life by up to 25%.

Diagram showing how every third redraw cycle is wasted with setTimeout-based animation
At top, each arrow represents a monitor refresh at 16.7ms periods. Below is a 10ms page redraw cycle. Every third redraw is wasted because the monitor will never show it. The result is choppy animations and wasted battery.

The requestAnimationFrame API is similar to the setTimeout and setInterval API’s developers use today. The key difference is that it notifies the application when the browser needs to update the screen, and only when the browser needs to update the screen. It keeps Web applications perfectly aligned with the browser’s painting, and uses only the necessary amount of resources.

If you take a look at this requestAnimationFrame example, you will notice that even though the animations look identical, the clock drawn with requestAnimationFrame is always more efficient in power consumption, background interference and CPU efficiency than the setTimeout clock.

Screen shot of the requestAnimationFrame API Test Drive demo
The requestAnimationFrame animation (right) is more efficient in power consumption, background interference and CPU efficiency than the setTimeout animation (left).

It is a simple change to upgrade your current animations to use this new API. If you are using setTimeout(draw, PERIOD); in your code, you can replace it with requestAnimationFrame. The requestAnimationFrame API is the furthest along of these three API’s with vendor prefixed interoperable implementations available starting with Firefox 4, Chrome 13, and IE10.

Remember, requestAnimationFrame only schedules a single callback, like setTimout, and if subsequent animation frames are needed, then requestAnimationFrame will need to be called again from within the callback. In this Platform Preview, IE implements the API with a vendor prefix like other browsers. Here is an example of how to write cross-browser mark-up that is future proof:

// Future-proof: when feature is fully standardized

if (window.requestAnimationFrame) window.requestAnimationFrame(draw);

// IE implementation

else if (window.msRequestAnimationFrame) window.msRequestAnimationFrame(draw);

// Firefox implementation

else if (window.mozRequestAnimationFrame) window.mozRequestAnimationFrame(draw);

// Chrome implementation

else if (window.webkitRequestAnimationFrame) window.webkitRequestAnimationFrame(draw);

// Other browsers that do not yet support feature

else setTimeout(draw, PERIOD);

Thank you, to everyone in the W3C Web Performance Working Group for helping design these APIs, and thanks to other browsers, for starting to implement these APIs with an eye towards interoperability. With these APIs, Web developers can create a faster and more power conscious Web.

—Jatinder Mann, Internet Explorer Program Manager