-
Notifications
You must be signed in to change notification settings - Fork 22.8k
Description
MDN URL: https://developer.mozilla.org/en-US/docs/Web/API/Performance/now
I've edited this issue a number of times, because monotonic timing in browsers is a deep rabbit hole of standards, implementations, operating system clock APIs, and clock hardware (see w3c/hr-time#115). The material below attempts to accurately and concisely document current browser behavior.
What information was incorrect, unhelpful, or incomplete?
There are several components of the documentation that are outdated or incomplete.
High Resolution Time vs. High Resolution Time Level 2
The semantics of performance.now()
changed from the original High Resolution Time spec to the Level 2 spec. In the original spec, performance.now()
was relative to performance.timing.navigationStart
from the Navigation Timing spec. In the Level 2 spec, performance.now()
is relative to performance.timeOrigin
, which is defined in the spec.
There are two key differences between these reference times.
- The triggering conditions for
navigationStart
andtimeOrigin
are a little different.navigationStart
timestamps a document fetch or an unload prompt (if any), whiletimeOrigin
timestamps creation of the browsing context (if no prior document), an unload prompt (if any), or the start of navigation (as defined by the HTML spec, which is a few steps before fetch). navigationStart
is set with the system clock, which might not be monotonic and might not be consistent across navigation events.timeOrigin
, by contrast, is set with a shared monotonic clock that is defined to be monotonic, consistent across globals, and initially synced to the system clock (e.g., on browser startup). These properties means that comparing timestamps across webpages with the original spec (performance.timing.navigationStart + performance.now()
) has clock change risks, while comparing timestamps across webpages with the Level 2 spec (performance.timeOrigin + performance.now()
) doesn't have clock change risks.
Ticking During Sleep
The original High Resolution Time spec does not address whether performance.now()
should tick during sleep. There was consensus for the Level 2 spec that performance.now()
should tick during sleep (see w3c/hr-time#65), but the text of the spec is somewhat ambiguous about sleep behavior and whether that's a normative requirement (see w3c/hr-time#115).
Here's a summary table of how browsers appear to currently handle sleep, where ✅ means performance.now()
keeps ticking and 🚫 means it doesn't.
Chrome/Chromium (bug) | Firefox (bug) | Safari/WebKit (bug) | |
---|---|---|---|
Windows | ✅ | ✅ | N/A |
macOS | 🚫 | 🚫 | 🚫 |
Linux | 🚫 | 🚫 | 🚫 (except maybe WebKitGTK?) |
Android | 🚫 | 🚫 | N/A |
iOS | N/A (WebKit wrapper) | N/A (WebKit wrapper) | 🚫 |
performance.timeOrigin in Chrome and Firefox
There is currently a bug in Chrome where performance.timeOrigin
is set for each global with the system clock rather than a shared monotonic clock. As a result, comparing High Resolution Time Level 2 timestamps across webpages in Chrome has clock change risks.
There is also currently a bug in Firefox where performance.timeOrigin
is set with a monotonic clock that is synced to the system clock once per process, rather than with a shared monotonic clock that is synced to the system clock once on browser startup. The result is the same: comparing High Resolution Time Level 2 timestamps across webpages in Firefox has clock change risks.
Clock Drift on macOS
The current macOS implementation of performance.now()
in Chrome/Chromium, Firefox, and Safari/WebKit uses a monotonic clock that does not allow for even small, monotonic adjustments (e.g., NTP oscillator corrections). The result can be clock drift between the system clock and High Resolution Time monotonic clocks. Chrome has a bug open on this issue.
Specific section or headline?
This content probably belongs in the general description of performance.now()
because of the significant consequences. Components might also belong on the performance.timeOrigin
and DOMHighResTimeStamp
pages.
What did you expect to see?
- The description is for High Resolution Time Level 2, but the example is for the original spec (referencing
performance.timing.navigationStart
). The page should probably include a description for both versions of the spec, examples for both versions of the spec, and an explanation of how the two versions differ, since the changes are subtle and Safari/WebKit hasn't implemented Level 2 yet. - A description of the browser- and platform-specific inconsistencies in sleep behavior, and what that could mean for use cases.
- A mention of the Chrome and Firefox
performance.timeOrigin
bugs, and what those could mean for use cases. - A mention of the High Resolution Time clock drift behavior on macOS, and what that could mean for use cases.
- An explicit indication that, while Safari/WebKit does support
performance.now()
, it has implemented the original High Resolution Time semantics and not the High Resolution Time Level 2 semantics. - Further explanation of the High Resolution Time Level 2 shared monotonic clock and per-document monotonic clock concepts would be valuable.
Did you test this? If so, how?
I've confirmed the following behaviors with both testing and code review:
- Ticking During Sleep
- Chrome: Windows, macOS, Linux
- Firefox: Windows, macOS, Linux
- Safari: macOS
- Time Origin Set with the System Clock
- Chrome: macOS and Linux
- Firefox: macOS and Linux
- Clock Drift on macOS
- Chrome: macOS
- Firefox: macOS
- Safari: macOS
MDN Content page report details
- Folder:
en-us/web/api/performance/now
- MDN URL: https://developer.mozilla.org/en-US/docs/Web/API/Performance/now
- GitHub URL: https://github.com/mdn/content/blob/main/files/en-us/web/api/performance/now/index.html
- Last commit: 86a69ae
- Document last modified: 2021-04-08T14:56:01.000Z