Loading and timers tasks run between DOM dirty and BeginMainFrame severely delaying Airbnb TTI and FMP |
|||
Issue descriptionGoogle Chrome 71.0.3578.98 (Official Build) (64-bit) Revision 15234034d19b85dcd9a03b164ae89d04145d8368-refs/branch-heads/3578@{#897} Platform 11151.61.0 (Official Build) stable-channel eve I see this on both my Macbook Pro and Chrome OS (Pixelbook). What steps will reproduce the problem? (1) Load https://airbnb.com/?force_loop=1 repeatedly. (2) Look for the large enqueueSetState script block. (3) Look for the Layout and Paint tasks that should come after it. What is the expected result? A BeginMainFrame always follows a long task that made modifications to the DOM. ex. if 300ms of script run, and it changed the DOM, then the next task should be a BeginMainFrame. What happens instead? Timers (ex. setTimeout) and Loading tasks (ex. scripts running) seem to occasionally sneak in between the long task and the BeginMainFrame. These new tasks can themselves take a long time, meaning we end up with super long frames which delay TTI and FMP. Note that this doesn't always reproduce, but it does happen fairly often. ex task order: React hydrate = 300ms <-- DOM is dirty. async script = 150ms image load task = 5ms image load task = 5ms begin main frame = 40ms <-- layout etc. finally paints. And now this frame takes 500ms instead of 300ms. This is making is difficult to meet RAIL and responsiveness guidelines on airbnb.com because even if we break up the long tasks into smaller chunks we don't see paints between them so we're not getting the improved TTI we'd expect. The current behavior doesn't seem to make sense since Chrome is missing a ton of VSyncs while running loading tasks, after already having missed a ton of frames in the previous task. If any script runs longer than a few frames (ex. 50 or 100ms) and the DOM is dirty (layer_tree_view_->SetNeedsBeginFrame() was called) then the next task seems like it should be BeginMainFrame.
,
Jan 12
,
Jan 14
Thanks for the traces! We currently up the priority of BeginMainFrame tasks after input events[1] and during certain scroll gestures. I think we should try to simplify the logic to always treat BeginMainFrame as high priority, but the challenge is doing so in a way that doesn't cause long-running BeginMainFrame tasks to starve out everything else. Since BeginMainFrame can often scheduler another BeginMainFrame (e.g., through rAF), it's a little too easy to end up in a situation where nothing else runs. I think we need to do a little brainstorming to figure out the best approach here. [1] As an experiment: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.cc
,
Jan 14
Thanks for the traces! It's really interesting, especially given that we also have exact opposite of a problem in Chrome (issue 461877), where we schedule BeginMainFrames too often. I think that we might need to expose a some sort of a Web API to allow the page to hint that a BMF is needed (pleaseCompositeNow() or a requestAnimationFrame with a priority). +panicker@ who is working on the new scheduling API for the web.
,
Jan 18
(5 days ago)
This is certainly interesting, I expect there are many cases where prioritizing rendering during loading actually hurts TTI by allowing rendering to starve loading work. I can see a case for experimenting with prioritizing rendering until FCP (atleast). related issue: https://bugs.chromium.org/p/chromium/issues/detail?id=772528 Question: Are the loading and timer tasks your application code or framework / React code? would you consider using rIC for the work that is pushing out rendering during loading? If not - why? If yes - then we have an effort around Main thread scheduling that could make this type of prioritization potentially easier with semantic priorities. https://github.com/spanicker/main-thread-scheduling We are working closely with React, also I'd been meaning to reach out to you on this topic! |
|||
►
Sign in to add a comment |
|||
Comment 1 by esprehn@chromium.org
, Jan 12