Skip to content
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

can performance.now() timers be frozen for background tabs, etc? #65

Closed
wanderview opened this issue Apr 8, 2019 · 13 comments · Fixed by #69
Closed

can performance.now() timers be frozen for background tabs, etc? #65

wanderview opened this issue Apr 8, 2019 · 13 comments · Fixed by #69

Comments

@wanderview
Copy link
Member

Currently users in chrome are seeing relatively large divergence from Date.now() and timeOrigin+performance.now(). We believe this is likely due to chrome allowing the performance.now() to counters to be frozen for some periods, like when a tab is in the background. See:

https://bugs.chromium.org/p/chromium/issues/detail?id=948384

While the spec mentions clock skew and system adjustments, its not clear to me if the browser is allowed to freeze counters for long periods. This can lead to two tabs for the same site having drastically different times that can no longer be compared.

If we cannot compare across tabs with performance.now(), must sites use Date.now() if they want this kind of comparison? This would seem unfortunate to me.

@wanderview
Copy link
Member Author

cc @yoavweiss

@yoavweiss
Copy link
Contributor

Yeah, I would think that even if setTimeout() timers are being frozen or slowed down, performance.now() wouldn't, similarly to Date.now().

@shubhie - thoughts?

@npm1
Copy link
Contributor

npm1 commented Apr 9, 2019

If one process is frozen and the other is not then it does not make sense to compare these timestamps regardless: one will do some work, the other won't, and thus it's unclear to me what you'd gain from such a comparison. Either way it is implemented, there is a problem and I think the goal should be to detect and ignore timestamps affected by frozen process. So I think the solution is to have heuristics to detect these rogue timestamps. Or an API telling you when you froze...
@spanicker (are these two linked to the same person?)

@wanderview
Copy link
Member Author

wanderview commented Apr 9, 2019

If one process is frozen and the other is not then it does not make sense to compare these timestamps regardless: one will do some work, the other won't, and thus it's unclear to me what you'd gain from such a comparison.

Any site that does cross-tab coordination (think docs with multiple tabs editing the same file, etc) may want to have consistent time measurements. For example, if tab A changes the underlying data model then the site might want to measure how long it takes for tab B and tab C to see the results. If tab C is suspended for multiple seconds, I don't think it makes sense to lie to the site and claim that this operation took only a few milliseconds instead.

Also, sites like this might want to store things in storage around when operations occur so that ordering can be performed. Losing time in these measurements could corrupt their data consistency, etc.

I guess this comes back to the target use case for performance.now(). Is it purely for measuring events within a single page? Or is it meant as a faster, monotonic replacement for Date.now() that can be used to reason about time in a consistent manner?

@spanicker
Copy link

Freezing of background pages can be detected with freeze() API .

Also if the page is frozen then you cannot really run javascript on it (after freeze callback) so not sure if / how this is related to freezing in background.

@spanicker
Copy link

This is probably related to throttling in background (not freezing) which is not a standardized concept and is a power-saving intervention.

@yoavweiss
Copy link
Contributor

The underlying question here is "should performance.now() be throttled when e.g. setTimeout() is?".
I'd argue that it shouldn't, and it needs to represent the actual time passed, in sync with other (potentially not-throttled) tabs/workers.

/cc @igrigorik for thoughts

@igrigorik
Copy link
Member

I'm not sure I understand what it means to throttle performance.now().

As in, it's a timestamp, and just as I would expect Date.now() to return the current time, I would expect performance.now to return current and correct high-resolution time. If all JS execution is throttled, that's an entirely different matter though..

Am I missing something?

@wanderview
Copy link
Member Author

Instead of comparing to throttling setTimeout(), consider more the situation where the cpu is put into low power mode and stops high performance counters. Should performance.now() "lose" this time because its underlying counters stopped or slowed?

If you're trying to reason about timing of your system across multiple tabs over longer periods of time I feel like it should not lose time here.

@igrigorik
Copy link
Member

I agree. One would not expect Date.now() to time dilate when in low power mode, and it would extremely confusing and weird for performance.now() to count time differently; time advances at same rate regardless of what CPU mode you're in.

If we consider high performance counters significant overhead for such mode — do we really? — I could see a path where resolution is reduced down to what Date.now() would offer, but then that compromises core use cases of high resolution time. Which is to say, my hunch is that the answer here should be "no, we don't reduce resolution", unless there is strong evidence showing that it would be a huge performance win for the user.

@skyostil
Copy link

As far as I understand, the issue isn't about reducing overhead as such, but more about using timestamps which do or do not keep advancing when the system suspends. I think we could pick either option, but right now Chrome isn't consistent about it.

There's some previous discussion re: Chrome here: https://bugs.chromium.org/p/chromium/issues/detail?id=166153

@npm1
Copy link
Contributor

npm1 commented Apr 23, 2019

We discussed this at the call, and people seemed to agree that we should not freeze the performance.now() timer when the tab is frozen or when the computer goes to sleep. I think we'd like to add at least a non-normative note stating this in the spec, and while we cannot add WPT tests, we should look at implementations and file bugs against those which do not comply with this (for example, Chrome).

@igrigorik
Copy link
Member

@npm1 yep, that behavior makes sense and +1 for adding a note for this 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants