-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Timer order and timer throttling for hidden pages #5925
Comments
This seems like a reasonable loosening to me, if it's indeed the route browsers are going down. @rniwa @annevk, any thoughts?
Probably the spec way to do that is within the same task. Since the sentence you mention is already pretty high-level, we could just expand it to
(or some variant of that which makes the now-extra-long sentence a bit more readable.) |
I'm not sure how Firefox's approach breaks the ordering guarantees and from OP it's not directly clear to me why it would be desirable to do so. cc @farre |
Regarding Firefox and tracking/analytics scripts, the MDN documentation mentions that for tracking scripts, "In background tabs, however, the throttling minimum delay is 10,000 ms, or 10 seconds, which comes into effect 30 seconds after a document has first loaded." This suggests to me that the timeout values for certain timers (coming from certain scripts) can be increased more than others coming from different scripts. But ordering guarantees are for method context (document or worker), not on a per-script basis, so it seems like this can potentially violate the spec ordering. For example, suppose > 30 s after page load the following sequence occurs, in short succession:
IIUC per spec, if (1) happens before (2), But if these act like
then the opposite order seems possible. I’m not sure how this is implemented in FF (or if this is up-to-date), so insight here would be great! I also don’t think this is likely observable or problematic, but I am wondering if it’s technically a spec violation, and if so, should the spec be updated. As to why we’re (Chromium) interested in this, we’d like to throttle based on nesting level (similar to Safari), applying further throttling to deeply nested timers. We think that deeply nested timers are the most problematic in terms of power consumption and differentiating strikes a good balance between saving power and not breaking certain use cases (see also blink-dev discussion). It’s still possible to differentiate based on nesting level and preserve ordering, but would require special handling for detecting ordering violations and running any throttled deeply nested callbacks whose timeout is <= the non-nested timer first. We feel that simply differentiating them and scoping the ordering guarantee to a task will:
|
So I looked through our implementation, and at one point we had a setTimeout where if it was called from a script on our tracking protection list, it would potentially be executed out of order. We backed that out, because it broke too much stuff, and we instead opted to go with a more general throttling strategy. Ordering seemed to be more important that we thought. So Firefox does respect ordering, when the method context is the same, although MDN says otherwise. |
@farre Thanks a lot for the info and looking at the implementation. Were you able to determine if the breakages were due to the longer delays/extra throttling, or if it was because of ordering? @rniwa any thoughts from the WebKit side, and do you have a sense of how much broke as a result of WebKit's additional throttling of nested timers? TIA. |
We experimented a lot with grace periods before throttling would start at all, but problems still remained so we definitely got the impression that order was an issue. |
It seems like a good idea to update the spec to allow what implementations do in practice. I'm not an expert on our timer code and from a quick scan, I can't tell if it would violate the ordering guarantees, but the code definitely does track and care about nesting level of non-repeating timers. Besides @rniwa it's possible @cdumez would know what's up here. |
Per the current spec (step 16 of the timer initialization steps), there’s an ordering guarantee such that when calling
setTimeout(callback, timeout)
,callback
will not run until othersetTimeout
callbacks with a timeout value <= |timeout
| have run, for the same method context (and % nesting level adjustment in step 11).For hidden pages, UAs often apply throttling to timers to save power, sometimes in ways that break this ordering guarantee.
My understanding of Safari’s approach is that they treat deeply nested timers differently, only throttling timers that have reached a certain nesting level, which breaks this ordering guarantee (i.e. new timers with equal timeout values can run before deeply nested timers).
Per MDN documentation of setTimeout, Firefox further treats timers in tracking scripts differently, applying additional throttling in background. I think this probably also technically breaks the ordering guarantee, although it seems safe to do so.
Chromium’s background timer throttling implementation so far has respected this ordering, but we are working on more aggressive timer throttling and would like to try Safari’s approach of treating deeply nested timers differently.
I’m wondering if we should update the spec to relax this ordering guarantee to match what UAs are doing? I think providing a guarantee within the same callback (stack) makes sense, but I'm not so sure about across async hops. For example:
An ordering guarantee here makes sense, even for background pages.
But what about here?
Thoughts?
The text was updated successfully, but these errors were encountered: