Understanding Chrome Dev Tools timeline

1.6k Views Asked by At

I'm trying to understand why I have several Long Frames reported by Chrome Dev Tools.

enter image description here

The first row (top of the call stack) in the flame chart are mostly Timer Fired events, triggered by jQuery.Deferred()s executing a bunch of $(function(){ }); ready funcs.

If I dig into the jQuery source and replace their use of setTimeout with requestAnimationFrame the flame chart doesn't change much, I still get many of the rAFs firing within a single frame (as reported by dev tools) making long frames. I'd have expected doing the below pseudocode:

window.requestAnimationFrame(function() {
    // do stuff
});

window.requestAnimationFrame(function() {
    // do more stuff
});

to be executed on two difference animation frames. Is this not the case?

All of the JS that is executing is necessary, but what should I do to execute it as "micro tasks" (as hinted at, but not explained here https://developers.google.com/web/fundamentals/performance/rendering/optimize-javascript-execution) when setTimeout and rAF don't seem to achieve this.

Update

Here's a zoomed in shot of one of the long frames that doesn't seem to have any reflows (forced or otherwise) in it. Why are all the rAF callbacks here being executed in one frame?

enter image description here

1

There are 1 best solutions below

3
On BEST ANSWER

Long frames are usually caused by forced synchronous layouts, which is when you (unintentionally) force a layout operation to happen early.

When you write to the DOM, the layout needs to be reflowed because it has been invalidated by the write operation. This usually happens at the next frame. However, if you try to read from the DOM, the layout happens early, in the current frame, in order to make sure that the correct value gets returned. When forced layout occurs, it causes long frames, leading to jank.

To prevent this from happening, you should only perform the write operations inside your requestAnimationFrame function. The read operations should be done outside of this, so as to avoid the browser doing an early layout.

Diagnose Forced Synchronous Layouts is a nicely explained article, and has a simple example demo for detecting forced reflow in DevTools, and how to resolve it.

It might also be worth checking out FastDom, which is a library for batching your read and write. It is basically a queuing system, and is more scalable.

Additional Source: What forces layout / reflow, by Paul Irish, contains a comprehensive list of properties and methods that will force layout/reflow.

Update: As for the assumption that multiple requestAnimationFrame calls will execute callbacks on separate frames, this is not the case. When you have consecutive calls, the browser adds the callbacks to a document list of animation callbacks. When the browser goes to run the next frame, it traverses the document list and executes each of the callbacks, in the order they were added.

See Animation Frames from the HTML spec for more of the implementation details.

This means that you should avoid using the consecutive calls, especially where the callback function execution times combined exceed your frame budget. I think this would explain the long frames that aren't caused by reflow.