Developers often focus on creating elegant code that is short and straightforward. However, this can kill browser performance when it fails to respect the way browsers actually render applications, said Andreas Gal, Mozilla CTO, at the Fluent Conference in San Francisco.
This is important because modern devices including smartphones and PCs generate user interface (UI) animations using a stream of images. A fluid graphic experience is presented at 60 frames per second (FPS), which corresponds to about 16 milliseconds (ms). Every time the browser needs to present a new image, the application needs to be ready with the updated image frame. If delays in the application cause it to miss one frame, people will notice, and if two frames are missed, users will complain.
Serial rendering in a parallel world
Use absolute positioning for layout
The principle purpose of layout functions is to present the boxes on the screen, but it can be tricky when the positions of the boxes are related to each other. When boxes do get moved around, they can cause other boxes to change positions and might require the application to recalculate the size of other boxes. Using absolute positioning rather than relative positioning makes it easier for the application to proceed smoothly without having to update boxes that are not shown on the screen.
Favor translation and alpha compositing
It is also important for developers to understand the impact of different graphics manipulation techniques. Mobile and desktop browsers are good at translation and alpha compositing. The device's GPU can often help accelerate this process. But changing the scale of elements rendered onto a screen can lead to performance delays. As a result, most CPUs cannot render scaled images at 60 FPS smoothly.
Avoid animated GIFs
Animated GIFs are growing in popularity on many sites owing to their small file size. However, they should be avoided when possible, Gal argued. Use video for animations rather than GIFs to achieve good performance. When a browser tries to animate a GIF, it uses the change in images to render the objects. Although the files can be small, rendering them taxes CPUs and memory. For example, a 200 KB animated GIF can require gigabytes of internal memory to render. Video formats are much easier to render, can better leverage the GPU, and make it easier to throw out frame data after it is presented.
Avoid stroking images
Line up image elements with pixels
It is also important to ensure that image elements align with device pixels. When image elements are not aligned, the browser will try to represent that as closely as possible. This can become particularly demanding when the user scrolls and the browser is trying to recalculate how to render the image element across pixels. It is easy to get this wrong when using canvas functions to render elements.
Avoid reading back from the GPU
Developers need to understand how the GPUs are architected to process image data. Don't read back pixels, Gal said. Most GPUs have a separate memory system from the main CPU. The CPU sends blocks of graphics to the GPU. The limited interconnect between the GPU back to the CPU can create a bottleneck when the application tries to move data back before rendering.
Understand layer optimizations
Another good practice is to understand how the browser splits up an image into layers. The idea of layers is to allow GPU cores more manageable chunks of graphics to work with. It is easy to do translation and alpha compositing on the GPU. The browser uses heuristics to infer good boundaries, which can create some artifacts. Therefore use tooling to make sense of how the browser splits up images.
Why HTML5 implementations should happen now
Gal observed that there are many ways to kill the performance of HTML5 applications, and these tips are merely a starting point for what can go wrong. When problems do occur, it's a good idea to run the code through a profiler to help identify the specific application logic creating the bottlenecks. The Octane 2.0 benchmark tool makes it possible to assess where these various pauses occur, and works better for measuring code changes on user experience than older benchmark tools did. The JIT Coach component of Mozilla DevTools looks at the performance-critical code based on what the JIT compiler is doing. It is important to use code profilers rather than look at code directly in order to understand performance impact, Gal said.
Has elegant code created application performance bottlenecks for your enterprise? If so, let us know how you have managed this setback.