High Resolution Time Level 2 joined the list of web standards. The new standard updates and replaces the previous High Resolution Time Level Level 1 standard. Level 2 strengthens the reliability and precision of performance monitoring, animations, audio cues, and synchronization between browsing contexts.
The Web Performance Working Group has published High Resolution Time Level 2 as a W3C Recommendation. This specification defines an API that provides the time origin, and current time in sub-millisecond resolution. High Resolution Time Level 2 replaces the first version of High Resolution Time.
The Level 2 specifications aim at fixing edge cases and enabling new use cases. The specifications states:
The value of time [as measured by Date.now()] may not always be monotonically increasing and subsequent values may either decrease or remain the same.
[Additionally] for certain tasks this definition of time may not be sufficient as it does not allow for sub-millisecond resolution.
As a matter of fact, the following script computes a duration that may be, in some cases, zero or a negative number:
var mark_start = Date.now();
doTask(); // Some task
var duration = Date.now() - mark_start;
This unintuitive behavior stems from the fact that the ECMAScript Language specification (i.e. JavaScript) defines the Date
object as a time value representing time in milliseconds since 01 January 1970 UTC. Millisecond precision means that the measured duration may be 0, if the doTask
function executes fast enough. The measured duration may also be negative or very large if the system clock is adjusted backward or forwards while doTask
executes! This needs not only happen due to malicious endeavors. A change of daylight saving time may also skew the measurement.
The specs go on to identify several use cases that require sub-milliseconds time resolution. Developers creating animations with JavaScript may need the increased precision to: timely update the state of the animation; determine whether the animation is drawing at 60 frames per second; cue audio to a specific point in an animation or ensure that the audio is synchronized with the animation. Additionally, workers in multiple contexts can leverage the higher time resolution to synchronize and drive animation, audio, etc. (in a renderer context), or to create a unified view of the event timeline for the entire application.
While the Date.now
API stands unchanged, the Level 2 specification adds the DOMHighResTimeStamp
type, the performance.now
method, and the performance.timeOrigin
attributes of the Performance
interface. The new APIs provide monotonically increasing time values with sub-millisecond resolution.
The performance.now()
timer is a relative measurement. It begins counting at 0 when its execution context is spawned: for example, when a page is opened or when a worker is created. Direct comparison of values returned by performance.now()
across execution contexts is thus not possible without a shared reference point. The performance.timeOrigin
returns the global system clock’s value when the timer initialization occurred.
A recent edition of the Professional JavaScript for Web Developers book gives the following example:
const relativeTimestamp = performance.now();
const absoluteTimestamp = performance.timeOrigin + relativeTimestamp;
console.log(relativeTimestamp);
// 244.43500000052154
console.log(absoluteTimestamp);
// 1561926208892.4001
The Level 2 specifications alerts of the security risks linked to the higher time resolution:
Cache attacks, statistical fingerprinting and microarchitectural attacks are a privacy and security concern where a malicious web site may use high resolution timing data of various browser or application-initiated operations to differentiate between subset of users, identify a particular user or reveal unrelated but same-process user data - see [CACHE-ATTACKS] [and [SPECTRE]] for more background.
To defeat the previously mentioned attacks, the new specification recommends a time resolution that is no less than 5 microseconds (thus 500 times lower than 1 millisecond). All major browsers have either reduced the maximum precision of performance.now()
accordingly or incorporated some randomness into the timestamp.
The new standard is already implemented in the vast majority of browsers.