Monday, April 23, 2012

Optimizing with the timeline panel

"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.

Orient yourself

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.

Is JavaScript slow?

In the above screenshot there are three JavaScript executions which look long enough to investigate. Hover on one to see the details.

This one took 405ms ("Duration"). The three together add up to 1.25 seconds or about a quarter of this 4.8 second page load. Alright, JavaScript looks slow. Should we hunt for loops to unroll? Shame! What's happening here is much more typical. Only 29ms ("Self Time") are spent actually executing this JavaScript and the other 372ms (purple "Aggregated Time") are spent on rendering operations triggered by the JavaScript.

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).

Now it may seem the way to speed this up is to optimize style recalculation time. Should we scour for descendent selectors? Not just yet. For both layouts and style recalculations, first ask whether the operation is necessary at all. It is usually possible to write a given script such that it triggers a maximum of one layout and one recalculation. So this is a red flag. To figure out what caused these recalculations, hover to see the responsible JavaScript call stack.

It turns out that each of the three major script executions are dominated by style recalculations which all have the addInlineCSS method on their callstack. Click the links to see the source. In the source view, the button with the two curly brackets formats the minified JavaScript for human readability.

The fix

Within 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!


Rob Colburn said...

Thanks much! While I understand reflow optimization, the timeline and it's many nodes is still daunting. This helps a bunch.

Steve Souders said...

So great to see you blogging, Tony. We want more!!

In case people wonder, the way to get to Timeline is Wrench | Tools | Developer Tools. Keyboard shortcut (on Mac) is Option+Cmd+i. "Timeline" is one of the "tabs" across the top of the tools panel.

I work at Google and use Chrome Dev Tools everyday, and I still didn't know about many of the features you pointed out here: pretty print formatting for minified JS, hover in timeline, how to tell JS execute time vs rendering time, and more.

I'm much more heartened about the power of today's dev tools, but also reminded of the complexity. There are SO MANY moving pieces it's hard to hone in the key part(s). Eventually the tools will do more of this for us. In the meantime, walkthroughs like this one are critical to helping web devs optimize web page performance.


Anonymous said...

Thanks, I learned a lot from your post!

DZONEMVB said...

Cool discussion of the possibilities of the timeline panel. Mind if I republish over at We'd like to curate some of your content. Just send me an email:

Amoral said...

Great article. Though I must ask. Wouldn't it simply be faster to include the styles and add appropriate classes to the elements? I know it's not your code and that that's not the focus of the article but I am curious if that way is faster than appending nodes to the DOM.

Tia Bolton said...

I'll sure be trying this process out in my system as well, especially when I want all my whole system to run faster. By the way, can you also share any application in archiving my stuff specifically for files or hard copy documents? Electronically or traditionally will surely help me a lot.

Education said...

For the optimization of site you need to have huge bulk of visitors which is possible through communication with people. Truly This post is precisely what I am fascinated. we require some more great qualified data. Good work. click here