Two and twenty years of browsers OR Jankfree Animation

2 June 2015 by Matthew Holloway

Why are some web pages faster than others? How are browsers going to change over the next few years? These are questions that web developers should know the answers to, but often don't.

A little known fact about the popular browsers in use today – Firefox, Chrome, Internet Explorer and Safari – is that they all began almost twenty years ago, in the same two year period of the late '90s, during the .COM boom. The Gecko Engine (Firefox) and Trident (Internet Explorer) both started development in 1997, with Webkit (Safari and Chrome) following in 1998. That was years before Intel shipped consumer multi-core CPUs, before AJAX, before JavaScript was taken seriously, and before anyone expected web pages to achieve 60 frames of animation each second. Fundamental software architecture decisions were made at this time and these fundamentals have proven very hard to readdress despite nearly 20 years of effort.

Making a new browser is a risky engineering challenge. Browsers take years to prototype and many more years to productionise. Even then it still might not succeed. While it's easy to make a toy browser that is faster at one thing, a real browser has to be well-rounded, it has to implement dozens of standards, and it has to be better than existing browsers. Due to these difficulties all popular browsers have instead chosen to optimise their late 1990s legacy, rather than starting anew (and to be fair, this has been successful-for the most part).

But one design decision has plagued all browsers: single-threading,

Being single-threaded means that one part of the browser can delay other parts from running1. If JavaScript takes too long to run it can delay CSS animation, or user clicks and button taps. If a CSS drop shadow takes a long time to compute2, then that can delay JavaScript. This all makes for a sluggish web page. Some of these issues aren't the fault of browsers themselves because they're required by W3C Web Standards, but others are simply browser flaws. There's no good reason why an <iframe> on another domain should cause delays in the 'parent' web page, yet it does.

So why do all these animation and JavaScript delays even matter? Depending on your web page, or web app, you might feel that this is not an issue for you. Every software has different requirements, and currently there's still a place for non-animated sites and apps, however over the past few decades people's expectations of user interfaces have increased. When Google Chrome was released in 2008 it increased people's expectations with the fastest browser, and now all other browsers have mostly caught up. Modern apps regularly run at 60 frames-per-second. Animation is now everywhere, and people are asking for more than ever from their browsers.

CREDIT: Google Material design.

These animations can assist people to understand the information hierarchy of the web page. In 'Consistent Choreography' [above] the first item appears a fraction of a second before the others – drawing peoples attention to the most important item. Menus slide out rather than abruptly appearing. Toggle buttons transform to indicate their current action of 'Open' or 'Close'. These are all subtle details, and any individual feature is debatable, but together they add up to make for a more coherent and smoother user experience. It can also make people more engaged. Facebook has done A/B tests and found that user engagement is correlated to frames-per-second. The jargon term "Jank" means jerky animations, and conversely 'Jankfree' refers to smooth animation.

A popular myth is that the human eye only needs about 30 frames per second (fps) to perceive motion, but that's just a minimum, and even then it's only really applicable with motion blur. Video cameras recording real life will get motion blur for free, but digitally composited web pages simply don't and so a significantly higher frame rate is needed. Of course, there are 1000 milliseconds (ms) in a second. Therefore at 60fps there are only 16ms available for each frame. In practice a web page has even less time than that (because the browser will have other things to accomplish during that time) and so a more realistic target is 14ms. That means that no JavaScript operation, or CSS, should take more than 14ms to complete.

Unfortunately, even with a tight millisecond budget there can still be janky animation –in part– due to this nearly 20 year old architecture.

In 2012 and 2013 there were another 2 years of significant browser changes, perhaps the most significant since 1997 and 1998. After 4 years of competing on JavaScript speed, there was consensus amongst browser developers that JavaScript couldn't be optimised much more, and that other parts of the browser were worth addressing. Finally, they revisited the fundamentals of single-threading and animation. Firefox's organisation Mozilla began a project called Servo in 2012, and in 2013 Google forked Webkit into a new browser engine called Blink. Both projects have the goal of making multi-threading pervasive in the browser, and significantly reducing any animation delays.

Mozilla's Servo is a new browser written from scratch3. All other existing browsers are written in C++, but Servo is written in a new programming language called Rust which allows for safer multi-threading while also preventing many types of memory security problems. Servo is scheduled for an alpha-quality release this year (2015), but it will be a few more years until it's ready for general public use. Mozilla have some bold words to describe Servo "Our goal is nothing less than building the fastest and most secure browser engine, and we aim to succeed by miles, not inches. We aim for double the performance of current engines, with no crashes." This claim should be taken seriously, and results from their prototype browser are already promising:

CREDIT: A graph of Mozilla's Gecko vs Mozilla's Servo rendering (smaller bars = faster) (source)

Google's Blink isn't a new browser, but it began with a significant fork of Webkit – halving the size of its source code within a month. Google withdrew support for Webkit, and that project hasn't recovered4. Blink has been used in Chrome since version 28, and in Android since version 4.4. As Blink is a pre-existing browser it's harder to change, but Google have equally bold goals to bring significant multi-threading into the browser engine, and to reduce animation delays. This work is underway, however significant results are yet to be seen.

It will be some years until these plans come to fruition. In the meantime web developers have to work within the constraints of existing browsers. So what can web developers do?

Improving performance of web pages is best done through profiling. All modern browsers have excellent tools for this. In Google Chrome there's a frames-per-second counter that can be displayed on all pages, and profiling information can be collected on JavaScript. In Firefox there's a 'Performance' tab within its developer tools.

There are, however, some general lessons that apply to all current browsers:

  • Cache DOM selectors, avoid unnecessary reflow, and debounce frequently triggered events.
  • Opacity and Transforms are significantly faster than other animation methods because they're typically on a fast path that avoids recalculating the geometry of page objects (more commonly known as reflow).
  • CSS (such as box-shadow2) can often be computationally complex and it can even cause jank. A workaround is to turn off complex CSS while scrolling, and then reapply it afterwards.
  • Put long-running tasks in web workers (when appropriate).
  • Consider using <canvas> (perhaps React Canvas) to render content.

In the 1990s web pages were mostly static documents with little in the way of JavaScript interactivity. The 2000s brought about web applications with AJAX and high-performance JavaScript engines. It's looking like the 2010s will see browsers becoming high-performance animation engines too, able to compete with native apps and able to satisfy people's modern expectations of interfaces.

If you want to know more about how to make your web pages and apps fast, contact Catalyst IT.

Further Reading

the original talk that this article is based on,


1. This a generalisation, and of course there are modern techniques like Off-main-thread Compositing (OMTC) that have rearchitected some parts of browsers but the majority remains single-threaded. Multi-threading doesn't mean that things will necessarily be faster, but there certainly are many areas within browsers that could be improved with it. Finally, there are approaches like preemptive multitasking but they've been excluded for clarity.

2. Yes, CSS can actually cause jank too.

3. Except for the JavaScript engine (written in C++) which is shared with Gecko, and may be sandboxed within Servo using NaCL Gaol (Update: article originally said NaCL but this was wrong, it's unclear what they will use but Gaol is relevant).

4. A graph of contributions to the Webkit project via Browser Contributions.pdf