STR: 1. Open up several tabs. My testing tabs were https://www.mozilla.org, https://en.wikipedia.org and http://www.cbc.ca 2. Open the Browser Console or Browser Toolbox (and then switch to the Console) 3. Type: gBrowser.tabpanels.removeAttribute("async"); and press enter 4. Switch to the mozilla.org tab. 5. Wait 5-10 seconds to (hopefully) ensure that the cached resources from the other tabs have been cleared 6. Using the keyboard, switch back to one of the other tabs ER: The content should be presented at the same time as the tab strip updates to the new selected tab. AR: The content appears to be updated first! This is highly unexpected - it means that the rendered layers were somehow still available on the compositor. We should try to understand how this works.
Okay, I think I've pieced together what's happening here. Here's a profile from the Quantum 2018 Reference device where I reproduced the issue: https://perfht.ml/2Eq3vxl There are a few key things to notice: 1. Very low sampling rate in the content process, but the markers / headers are in the right spots, and that's probably the most interesting part 2. The parent process is very busy dealing with all of the style and layout work to supply logging output to the Browser Console (since I have tab switch logging turned on). So here's what I think's happening: 1. The tab switch starts, and we message the content process to start painting, as per usual 2. The paint occurs, and the layers upload to the compositor. 3. The compositor receives the layers and tells the parent so that it can dispatch the MozLayerTreeReady event (which causes the rest of the UI to change, and for the deck to be flipped) 4. The parent, because it's so busy dealing with all of the traffic in the Browser Console, does not receive the MozLayerTreeReady event within 400ms. Meanwhile, because step 3 of the STR removes the "async" keyword from the binding, the deck flips right away, and we see the painted layers 5. Eventually, parent frees up enough to service the MozLayerTreeReady event, or to run the AsyncTabSwitcher timer. In the former case, we then update the browser UI - perhaps long after the layers had actually been shown to the user. In the latter case, we switch to showing a spinner until finally the MozLayerTreeReady event is serviced.
The good news is that this doesn't completely shatter my mental model of how all of this stuff works. The bad news is that I don't see right away how we can take advantage of this. Clearly, there are cases where the content processes is freer than the parent, and is able to paint right away, and what we're gated on is the compositor sending the MozLayerTreeReady event, and the ability of the parent process to service that MozLayerTreeReady event ASAP to update the browser UI.
Hmm. At a high level, maybe we could tag the spinner layer in some way for the compositor so it can recognize that it should not be displayed if we've already received the right layers from content?
Summary: Can still show some whole sites without calling renderLayers on the 2018 reference device → Handle case when compositor receives layers but MozLayerTreeReady will not be serviced by the parent in time
Whiteboard: [fxperf][qf] → [fxperf][qf:p3:responsiveness]
Possibly something to be fixed for lower end hardware, but without a clear way on what to do to improve the situation -> p3
Whiteboard: [fxperf][qf:p3:responsiveness] → [fxperf:p3][qf:p3:responsiveness]
You need to log in before you can comment on or make changes to this bug.