w3c / requestidlecallback

Cooperative Scheduling of Background Tasks
https://w3c.github.io/requestidlecallback/
Other
50 stars 19 forks source link

"deadline" in the "start an idle period algorithm" should be defined in terms of event loop #71

Closed rniwa closed 2 years ago

rniwa commented 6 years ago

Right now, The start an idle period algorithm defines the deadline as:

Let deadline be a time in the future until which the browser expects to remain idle. The user agent SHOULD choose deadline to ensure that no time-critical tasks will be delayed even if a callback runs for the whole time period from now to deadline. As such, it should be set to the minimum of: the closest timeout in the list of active timers as set via setTimeout and setInterval; the scheduled runtime for pending animation callbacks posted via requestAnimationFrame; pending internal timeouts such as deadlines to start rendering the next frame, process audio or any other internal task the user agent deems important.

However, the list of active timers is defined in terms of a global object. I don't think that's the intent here. It needs to be defined in terms of the event loop. Perhaps we need a list of active timers for the entire event loop to be defined in the HTML specifications itself.

rniwa commented 6 years ago

@rmcilroy @domenic

rmcilroy commented 6 years ago

I think this is best resolved by hooking into the HTML event loop spec as is being discussed in #70

yoavweiss commented 5 years ago

So seems like this is blocked on #70

yoavweiss commented 5 years ago

@rmcilroy Would landing https://github.com/whatwg/html/pull/4104 fix this issue as well? Or is there extra work to be done here?

rniwa commented 5 years ago

No, we still need to define what it means for the event loop to be idle. The issue I raised is that just because this particular global object doesn't have any active timers, it doesn't mean other global objects such as those of iframe don't have a bunch of active timer soon to be fired. So this deadline needs to be computed the same way https://github.com/whatwg/html/pull/4104 defines the timing at which this algorithm is invoked.

rmcilroy commented 5 years ago

Right, this would need more work. It's not entirely clear how we could spec this - the current spec for setTimeout / setInterval relies on "wait for timeout milliseconds in parallel" before queuing a task on the task queue, so there isn't actually anything queued anywhere while the timer is pending that we could surface to the rIC algorithm. Any thoughts?

domenic commented 5 years ago

How is it implemented? Can we use that as inspiration for the spec?

rmcilroy commented 5 years ago

In Chrome the delayed tasks are posted on a task queue while they are pending, ordered by their timeout/delay (this includes internal tasks as well as setTimeout tasks). We set the deadline to be the time of the earliest task in the queue (and also cap to 50ms or next frame deadline if we are rendering).

farre commented 5 years ago

This is pretty much how we do it in Gecko as well.

rmcilroy commented 5 years ago

It seems like modifying the HTML spec to accommodate this would be a decently big effort, and actually thinking about it I'm not sure how much it helps given the spec also wants to let the UA shorten the deadline earlier for internal tasks as well as those posted via the HTML spec, and to use heuristics to predict the likelyhood of an external event happening during that time. I.e.:

pending internal timeouts such as deadlines to start rendering the next frame, process audio or any other internal task the user agent deems important.

How about moving the discussion of the setTimeout, etc. to a non-normative note, and make the normative section explicitly regarding the event loop, i.e.:

Let deadline be a time in the future until which the UA expects the window's event loop to remain idle. The user agent SHOULD choose deadline to ensure that no time-critical tasks will be delayed even if a callback runs for the whole time period from now to deadline.

Note: Typically the deadline should be set to the minimum of: the closest timeout for the list of active timers as set via setTimeout and setInterval to the window's event loop; the scheduled runtime for pending animation callbacks posted via requestAnimationFrame; pending internal timeouts such as deadlines to start rendering the next frame, process audio or any other internal task the user agent deems important.

WDYT?

yoavweiss commented 5 years ago

@rniwa friendly ping! :)

rniwa commented 5 years ago

Again, my main issue with the spec is that this isn't precisely defined. Adding a non-normative note wouldn't cut it. In general, if the spec doesn't meet the bar of specifying a feature to the extent it should, then the right call is to delay the publishing of the spec instead of hand-waving the definition of it. We can't spec a deadline by enumerating examples. That precisely is the current spec's wording I have an issue with.

And, again, "given browsing context's event loop" doesn't make sense because the event loop is a global concept shared across a unit of related browsing contexts.

rmcilroy commented 5 years ago

Fair enough, would someone be willing to add the necessary hooks into the HTML spec to make this happen? I don't have the bandwidth or experience with the HTML spec to do that at present.

yoavweiss commented 5 years ago

the spec also wants to let the UA shorten the deadline earlier for internal tasks as well as those posted via the HTML spec, and to use heuristics to predict the likelyhood of an external event happening during that time. I.e.:

pending internal timeouts such as deadlines to start rendering the next frame, process audio or any other internal task the user agent deems important.

Going back to this, and since the definition of "deadline" should also include heuristics regarding external events (which we don't intend to specify), I'm not sure what the benefits of specifying that would be.

@rniwa - are there any compatibility issues that you think will arise from keeping this value UA defined?

rniwa commented 5 years ago

@rniwa - are there any compatibility issues that you think will arise from keeping this value UA defined?

Obviously. You can have a timer inside an iframe or a window then the deadline according to the current spec would be ignoring that. It's true that we can observe what Blink and Gecko had implemented and not make such a stupid mistake but the purpose of the spec is to clarify what needs to be implemented even in absence of any implementation. If we're forced to reverse engineer what Blink and Gecko did to implement this in WebKit, what the heck is the point of having this spec at all?

yoavweiss commented 5 years ago

I believe the case of same-origin iframe or window are covered by the suggested normative language @rmcilroy suggested. Specifically, "Let deadline be a time in the future until which the UA expects the window's event loop to remain idle. " covers that case, as same-origin iframe or window share an event loop with the window.

Otherwise, I don't think that there will be benefits to defining UA-specific, internal events as part of the spec and it's better to keep them vague, to enable better flexibility when it comes to such heuristics.

That leaves us with the issue of timers. Timers do not currently queue tasks immediately, but only after the timer expired. They do register themselves on the "list of available timers", but that list is separate per global scope, even if multiple global scopes share an event loop.

So, maybe we can extend the suggested normative language and replace the current reference to timers of "the closest timeout in the list of active timers" with "the closest timeout in the list of active timers in any global scope that queues tasks on window's event loop".

Thoughts?

rniwa commented 5 years ago

"Let deadline be a time in the future until which the UA expects the window's event loop to remain idle. "

That wording would work if we can define what it means for an event loop to remain idle.

Let's consider the following clause in the event loop processing model which defines when to start an idle period algorithm:

If this is a browsing context event loop (as opposed to a worker event loop), and there are no tasks in the event loop's task queues which are associated with a Document that is fully active, and the event loop's microtask queue is empty, and none of the browsing contexts have a rendering opportunity, then for each browsing context, run the steps in the start an idle period algorithm, passing the Window associated with that browsing context.

This definition makes it crystal clear as to exactly what condition constitutes the start of an idle period and when the algorithm is invoked relative to all other things happening in the browser. We need something similar. We need exactly what remain idle means. Is it that we don't expect a task/microtask to be scheduled in the current event loop? Is it that the rendering opportunity won't be happening? etc...

As for timers, yeah, we probably need to define the time at which the next/closest timeout from the list of active timers of each document of the browsing contexts which use the same event loop as a given window's browsing context.

rniwa commented 5 years ago

Here is a list of things we discussed during F2F to explicitly list instead of "expect to remain idle"

rniwa commented 5 years ago

Now that the HTML spec has explicit task sources when queuing tasks from algorithms that run in parallel, maybe can tie the concept of deadline to that. In particular, maybe we can say the deadline is reached when a new task is being queued to the user interaction task sources?

rniwa commented 5 years ago

WDYT? @annevk @bzbarsky

yoavweiss commented 5 years ago

/cc @spanicker @shaseley - opinions on https://github.com/w3c/requestidlecallback/issues/71#issuecomment-501414810?

bzbarsky commented 5 years ago

That wouldn't address the timer issue, right? It would address user input preempting an idle period, though and seems sensible in that regard. It wouldn't be able to affect the deadline calculation, though, unless I'm missing something.

rniwa commented 5 years ago

@bzbarsky : Right, we have to handle the timer timeouts separately from the user inputs.

So my straw man proposal for when the deadline becomes 0 is as follows:

  1. The minimum time at which next timer or rAF callback fires.
  2. The time at which the user interaction task source gets a new task enqueued.
bzbarsky commented 5 years ago

So there are two meanings of "deadline", right?

1) What value is passed to the idle callback? 2) When do new idle callbacks stop getting run?

That proposal works for item (2), but I don't see how item (1) can depend on "The time at which the user interaction task source gets a new task enqueued", because that time is not known when the call happens, right?

rniwa commented 5 years ago

@bzbarsky : Right. I think (1) will depend on timers & rAF for now. We can add more things to the list as we find them.

rmcilroy commented 5 years ago

Right, for (2) we already have a hook in the step 4 of the IdleDeadline timeremaining() interface to set it to zero if a "time-critical task pending". I agree we could use the new user interaction task source to make this phrasing more precise.

rniwa commented 5 years ago

time-critical task pending

As I mentioned in https://github.com/w3c/requestidlecallback/pull/78, I don't think the phrase "time-critical task" would be any more precise than arbitrary time UA picks since there is no definition for being time critical.

rmcilroy commented 5 years ago

That's why I suggested changing that phrasing to be based on the new new user interaction task source.

rniwa commented 4 years ago

Per today's meeting, we tentatively agreed to define the deadline to be the minimum / earliest of:

rniwa commented 4 years ago

We should modify timer initialization steps to define the time at which each timer fires because there is no such a thing defined right now. In particular, the timeout only progresses while the document is fully active so that means it's not a simple wall clock or monotonic time that we can calculate.

It's possible for a timer in one document to not expected to fire because the timeout doesn't progress due to the document not being fully active.