Mobile Web So Fast Vin Diesel Wouldn't Race It

by Dave Arel

The availability of browser technology on almost any device has contributed to the increasing number of developers with a focus on creating performant web-based mobile applications. While in theory the web could be the future hub of mobile apps, mobile browsers have a long way to go.

The mobile web has several bottlenecks, but I’ve found the lack of efficient memory management to be the greatest. In order to build fast, scalable, content heavy applications in environments where memory is limited, optimizing is critical. With the lack of tooling and the ineficiencies of the garbage collector, optimizing becomes incredibly difficult.

Memory, however, is only an issue because of how visually complex our applications have become. Gone are the days of textualized websites and here are the days of cat gifs and memes.

While memory was and continues to be an inconvenience for Belly’s HTML5 Hybrid iPad application, it’s more a limitation of how much content we can realistically hold in memory at one time, and the ability to properly discard unused memory, rather than a direct performance issue. Unless that is, you use too much of it.

When it comes to the performance of mobile web apps today, one of the largest issues I find developers to be perplexed with is rendering performance. While native apps continue to leverage the many advantages they have over the browser or the UIWebView, one of the most noticeable is the use of the Graphics Processing Unit (GPU). While browsers nowadays make some use of the GPU, they are still a long way from optimal utilization. Regardless, a general understanding of their current implementations can go a long way in crafting performant mobile apps.

Rendering Engines

The browser’s rendering engine is what is used to parse the HTML, create the DOM tree, paint the styles, position elements, and draw them to the screen. Rendering engines have never been trivial. The lack of documentation and tooling to better understand how these engines output our content leads to a development style called: Trial and (mostly) Error.

While understanding the browser’s entire rendering process is helpful, I’m going to focus on the browser’s utilization of the GPU to create hardware accelerated composite layers which can drastically improve the performance of any application.

Composite Layers

By default browsers have traditionally relied entirely on the Central Processing Unit (CPU) to paint the output of a page. The CPU is an extremely powerful and versatile processor, but it’s not great at everything. Much like a high school Jock, CPU’s are great at sports, are incredibly good looking, and have all the right friends, but tell a CPU to create art and it will draw you a stick figure.

In comes The Graphics Processing Unit (GPU). The GPU is efficient at pixel operations (drawing and manipulating graphics) and excels with its ability to perform several simultaneous tasks. Modern browsers have a feature called accelerated compositing. With accelerated compositing, portions of the page are split into several layers (or “Backing stores”) which can be rendered by the GPU and drawn to the screen.

Without the use of the GPU and hardware accelerated compositing, the browser will render everything to a single GraphicsContext. If that GraphicsContext is invalidated (visually changed), the browser has to recalculate, repaint, and redraw the entire page. On a mobile device this usually results in noticeably slow rendering time.

Making use of the hardware accelerated compositor allows us to make changes to portions of the page without having to redraw the entire page. For Belly’s HTML5 hybrid application we built a custom HTML5 keyboard. While accelerated compositing was important for all aspects of our app, the keyboard is a simple and effective demonstration of the performance boosts compositing offers. Note: the keyboard is styled entirely in CSS, no images were used.

The image below shows the repaint process (in obnoxious yellow) with and without the use of compositing. Each button has an active-state, so any time a keyboard button is tapped the key needs to be recalculated, repainted, and redrawn. Without compositing, the entire keyboard is recalculated, repainted, and redrawn.

In real life (yes, this is real life), this results in a pretty major performance boost.

Non Hardware Accelerated vs Hardware Accelerated

Notice the delay not only in the active-state of each key press, but also the entry into the input field (which, by the way, is custom as well). Without the use of accelerated compositing, this would be a truly frustrating experience for any consumer. We’ve also composited the entire keyboard backing so that when it’s translated on and off the screen, it doesn’t have to be repainted. It only has to be redrawn.

How?

Well here’s the thing— Browsers don’t give us direct access to hardware acceleration. At least not in a predictable or standardized way. Like many performance related factors, browsers try and hide the complexity and provide you with opinionated optimizations. Regardless, there are several properties that are known to trigger hardware acceleration on elements. Most notably translateZ or translate3d :

.keyboard, .key {
  -webkit-transform: translate3d(0, 0, 0);
}

Compositing is great for animations because instead of having to recalculate and repaint the entire page every frame of the animation the GPU simply uses the cached bitmap to redraw the composited layer. This is incredibly fast. Because properties like translate3d are predicted to change or animate, browsers will offload that work to the GPU.

But beware: this isn’t guaranteed to always work. Browsers could change the way they utilize the GPU in future releases. In fact, just recently the w3c released a CSS Module spec called “will-change”. This will replace the translate hacks, allowing a developer to indicate to the browser an element is indented to change, as Paul Lewissummarizes in his article “Bye Bye Layer Hacks“.

Using Composite Layers to Pre-Render Content

Another truly neat aspect of composite layers is that the painting process can happen to an off-screen buffer, prior to being drawn to the display. Performance is largely perception, and pre-rendering a view that’s anticipated to be used can go a long way in improving the experience a consumer has with your application. At Belly we were able to get screen transitions to feel near instant by pre-rendering these screens, and simply translating that view to the display.

Why not Accelerate all the things?!

While in theory compositing every element on your page would result in a much faster interface, not all tasks are best performed by the GPU, and even so, memory doesn’t grow on trees and the GPU isn’t exactly conservative. A mobile device overusing hardware acceleration can result in a performance hit (Oh, the irony) or even crashing.

Bad:

// TRANSLATE ALL THE THINGS!!!!
* { -webkit-transform: translate3d(0,0,0); }

In summary

Accelerated compositing is strange in that it’s an extremely useful technology that the browser hackishly offers, yet it’s also a very under documented, unpredictable beast. If you intend to build a highly performant HTML5 mobile application, however, it’s essential to your success.

Related Articles

For more complete information about compiler optimizations, see our Optimization Notice.