atotic / event-loop

Deep dive into JavaScript event loop
400 stars 36 forks source link

Question about timer callbacks #4

Open prashantpalikhe opened 7 years ago

prashantpalikhe commented 7 years ago

In the repo, it mentions that the event loop tick picks out the oldest task in the queue, executes it, checks if rendering needs to be done, and after all that, moves onto the next tick.

while(true) {
    task = eventLoop.nextTask();
    if (task) {
        task.execute();
    }
    eventLoop.executeMicrotasks();
    if (eventLoop.needsRendering())
        eventLoop.render();
}

So, with that in mind, if I have two timers installed with setTimeout(fn, o) and the first timer callback dirties the DOM.

setTimeout(() => {
    document.body.innerText = 'DOM updated';
}, 0);

setTimeout(Function.prototype, 0);

I would expect the event loop to do the work in following order:

  1. Pick setTimeout callback and execute
  2. Rendering is necessary, so hit the rendering pipeline
  3. Pick next setTimeout callback and execute

But in Chrome's flame chart, I see

  1. setTimeout
  2. setTimeout
  3. rendering

screen shot 2017-10-04 at 21 36 23

Whats the explanation for this?

prashantpalikhe commented 7 years ago

According to my research, in Chrome, if the main thread needs to hit the rendering pipeline, it basically asks the compositor thread (impl thread) to signal it when to start generating frame. The compositor thread listens to underlying OS's vsync api to detect vsync intervals and therefore knows when is the good time to draw, depending on whether we recently drew, when the next frame is and other things. When compositor thread tells main thread to begin generating frame, main thread does several things which includes calling raf callbacks, performing pending layouts and recording drawing calls (main thread-side painting).

So in the above situation,

  1. the first settimeout callback dirties the DOM.
  2. Main thread asks impl thread to send begin-frame signal
  3. Meanwhile, executes second timeout callback
  4. Impl thread tells main thread to generate frame
  5. main thread performs pending layout/painting and ships a frame

Which in the flame charts translates to what we see

  1. setTimeout
  2. setTimeout
  3. rendering

I guess that explains what we see in the flame chart. Would be great if someone with deeper knowledge on these internals validate whether its true or not.