"I know I should look at Chrome's Timeline panel, but what do I do with it?" was roughly the opening line in two recent web performance meetings. In both we found nice speedups using the same mantra: "Don't ask how to make an operation faster, ask why it is done at all."
To ward off a third meeting, I decided to write about it. This is best demonstrated with a real world example, and it happens that there's a perfect one on Wikipedia.
Record a trace
To follow along at home, head over to your favorite lengthy Wikipedia article—mine is List of common misconceptions. Open the Inspector's Timeline panel, click the black circle record button at the bottom, refresh the page and finally stop recording after it loads. You now have an initially daunting trace of all the major steps of the page load.
The top timescale marks the document's
DOMContentLoaded event with a blue line and the window's
load event with red. In the screenshot above, I dragged the righthand slider in to the red line to zoom in on only the events which happened during the page load.
Finally notice the event coloring scheme: loading in blue, scripting in yellow and rendering in purple. In the remainder of the screenshots I've unchecked the blue box to hide loading events—perhaps a topic for another day.
Examine rendering operations
Expand the drop down to see the rendering operations: predominantly 4 style recalculations, each about 90ms. The other two scripts have very similar breakdowns (not shown).
It turns out that each of the three major script executions are dominated by style recalculations which all have the
execute method the culprit steps into the light: a loop that appends style elements to the document one by one. The browser does a full recalculation of all styles on the page each time this happens.
Fixing this is straightforward. Before appending to the DOM, either concatenate the CSS strings into a single style element or else coalesce the style elements into a DocumentFragment. This trace suggests that could chop almost a second off the page load.
I'd love to see this example fixed (hopefully in WebKit), but that's not the point of this post. There are various well known anti-patterns which can trigger wasteful rendering operations. They are easy to write and often not slow enough to worry about. Hopefully you've taken away the courage to open the timeline and diagnose the ones that do need to be optimized. Happy tracing!