-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Specify event loop integration / priority intent #67
Comments
FYI @sefeng211 and @smaug----. Working on this, I'll try to get a draft of a change sometime soon. Thanks for pointing it out. |
Thanks for the summary! |
I just realized some of those priorities in Chrome don't quite match Gecko. Especially the "Very High rendering" vs. "Normal rendering", so it is a bit unclear when we'd run 'user-blocking'. Also, do different tasks in normal priority have then some "subpriority", or do they get processed in the order they were created? Can 'user-visible' task be handled before pending 'Rendering default state' (I assume that means HTML spec's rendering update) And sorry about being so late with this. I had lost the email about this issue but sefeng reminded me about this recently. |
For some additional context, in Chrome the "update the rendering" steps happen in a separate task internally, which used to be scheduled at "normal priority". I think we used normal priority (vs. on every vsync) because rendering too much added latency to loading, for example. But that could result in too much lag in updating the UI, so we periodically boost the priority of these tasks to strike a balance. IIUC Gecko has a different approach (decreasing frame rate during loading?). We also didn't want user-blocking tasks to indefinitely starve rendering updates, and periodically boosting the priority of rendering ensures that. The thought is if user-blocking tasks are updating the dom, we don't want to starve showing that to the user. Also, if the browser decides to process input while user-blocking tasks are pending (which Chrome does), we'd want to update the UI asap. So the idea is that "user-blocking" tasks are a type of HTML task (and run in that part of the event loop steps), and the priority is meant to help choose between other HTML tasks (typically favored, but shouldn't block critical tasks like input), and choosing rendering opportunites wouldn't change.
Yeah, 'Rendering default state' means "update the rendering steps" -- which happens in a separate task in Chrome. The scheduler will run tasks in priority order, and posting/created order within that priority -- so no subpriorities within normal. You could probably think about "user-blocking" as a sub priority above normal, and "background" as a subpriority below normal. One other note: I know the HTML spec allows different task sources to be prioritized separately -- which could be implemented using subpriorities within normal priority, but in Chrome we mostly don't (input is the main exception, and recently we experimented with boosting priority of image loading tasks on the main thread, which helped improve CLS during loading). Partly we don't know what should be prioritized without developer hints, and extending the
In Chrome, yes -- it depends on the relative order they were scheduled. This is also true for other task sources, e.g.
No worries! Thanks for the questions. LMK if discussing this further in a WHATWG triage call/WebPerfWG session would make sense. |
Gecko deprioritizes animation frames during loading, so in practice that ends up reducing frame rate often. In Gecko "update the rendering steps" is also a separate task, it happens to be rather high priority. Input events are higher priority - or rather aligned with the task used for "update the rendering steps". So input events are usually dispatched right before rAF. Doesn't blink have rAF aligned input events too (except perhaps pointerrawupdate). Gecko tries to avoid starving rAFs and normal priority tasks. So if processing rAF takes (as an example on a common monitor) > 16ms, we do let normal priority tasks to be handled. And if normal priority tasks take lots of time, we do ensure rAF gets processed every now and then (our limit there, 4 * frame rate, isn't that different to Blinks 100ms ). But ok, maybe in Gecko 'user-blocking' tasks could be processed between input events and rAF (but perhaps rAF needs to get through every now and then, if 'user-blocking' tasks are slow). Scheduling is tricky. (Looks like I use "update the rendering steps" and rAF to mean basically the same thing) |
So I think in the spec we should define at least a bit more precisely how user-blocking and user-visible are expected to work vs rendering update. We probably want to let UAs to still tweak their scheduling quite a bit, if needed, but the high level expectations should be documented. |
@shaseley Has this been addressed at this point? |
Forking this from here into its own issue.
Problem: The way
scheduler
task priorities are integrated into the event loop in the spec is underspecified. The original goal was to allow UAs maximum flexibility to integrate these into their schedulers, but the intent is not clear, which is bad for other implementors and compat.Task Priorities in Blink
This section describes how Blink implements priority mappings, included for reference for how
postTask()
fits in. Typically, scheduled tasks run in priority order as follows:postTask()
taskspostTask()
taskspostTask()
tasksThis is the current state, but there are quite a few inactive — and a few active — experiments I left out.
Notes:
Specifying Priority
The intention of
postTask()
priorities:setTimeout()
and same-windowpostMessage()
(which is used as a scheduling API). But they shouldn't indefinitely block input and rendering.A challenge is that UAs are currently free to choose rendering opportunities and schedule between task types as they see fit, and I don't want to create a total ordering of tasks and stifle UA experimentation. But we need to make clear the intention and consider providing stronger guarantees.
This is also a challenge for
scheduler.yield()
, where want stronger guarantees (see this section). I wrote there about maybe using a denylist approach, where the relative ordering vs. some tasks sources is specified, providing some guarantees. Doing that for both APIs would be simpler/cleaner, and maybe a good place to start? And it could be potentially augmented with notes about intent and guidance.The text was updated successfully, but these errors were encountered: