Browser Performance Banes and Cheat Sheet

I gave a quick chalk-talk today that is maybe of general interest. I was talking about the few categories of Browser Performance Problems. These are fairly simple cost and consequence categories (say that three times fast) that often drive bad experiences.

Image for post
Image for post

The main pipeline is in some sense what the browser does “passively”; you make some DOM edits (either by downloading a new page or running script) and it responds with parse/format/layout/render/compose.

  • Parse: convert the text to internal data structures of the appropriate type
  • Format: convert declared styles to computed styles
  • Layout: consume computed styles to get position and size of every box
  • Rendering: draw the stuff that’s on the screen into a suitable buffer (maybe a bitmap, maybe a display list), breaking into 1 or more layers in the process
  • Compose: blend various layers to create the final display

Any given change to the DOM is going to require these processes to run and generally you’d like surgical changes as a consequence. How well the browser can consume your change and minimally recompute what’s necessary will tend to drive the responsiveness of your page (and its battery cost). Note different browsers respond differently, some changes that theoretically can be very economical are poorly implemented and so a large cost is incurred. You can often change your code to avoid these costs. Or request browser improvements.

On the right side we have the script operations. Again the code has to be parsed. It’s compiled minimally into bytecode, but potentially lowered all the way to native code. That code then runs, either interpreted or not. The dominant costs could be at any of these stages. Additionally JavaScript can create significant memory pressure, and that can cause material costs associated with garbage collections.

Connecting the left and the right side there has to be some kind of interoperability layer that allows the script to call into the browser’s native code processing. That code will typically do DOM manipulations but it might also do stuff like Canvas or WebGL. There could be costs associated with the layer itself or DOM costs driven by JavaScript.

There are two anti-patterns that are responsible for most of the horribleness you see on the web. Well, at least in my experience these are the two whoppers:

  1. Too much use of GetOffsetWidth and friends

The problem with those APIs is that they force a synchronous layout. A common JavaScript pattern is to add some stuff to the DOM, look at a width, add some more stuff, and so forth. When this happens you will get multiple layouts during that impulse of JavaScript work. This is likely to suck. You really want only one layout pass per presented-frame — or maybe even less if you’re just scrolling or something. If you force layouts you will be unhappy.

2. Too many timers.

The biggest drain on battery comes from the abundance of high frequency (60Hz) timers in web pages. Any kind of high frequency timer is going to prevent the CPU from going into a sleep state, that’s bad enough, but if you do expensive operations in your callbacks you will also materially affect render times. Ads on a web page tend to be the worst offenders “I think my ad should load its own copy of JQuery archived from 1847 and do some nice hefty computations with it.” Naturally the other ads are using JQuery from different centuries. * I know there was no JQuery in 1847, it only seems like there must have been when you have to decode the minified code…

The biggest power savings from browsers tend to come from advanced timer management. Which approximately consists of “You want a 60hz timer for your low priority stuff? Screw you, you’re getting 1Hz and you’ll like it.”

As indicated there is an achievement for doing (1) and (2) at the same time.

Naturally this isn’t everything; but this stuff comes up an awful lot.

The “F12” tools in the browsers can be invaluable for identifying all of these categories. Likewise Windows’ “WPA” toolkit can be invaluable for finding consumption and correlating it to markup.

Written by

I’m a software engineer at Facebook; I specialize in software performance engineering and programming tools generally. I survived Microsoft from 1988 to 2017.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store