Module: timing

This module facilitates timestamping events, using a standardized clock. When supported by the browser, WebScience uses the shared monotonic clock specified by the W3C High Resolution Time recommendation. Otherwise, WebScience uses the system clock.

Web Browser Clocks

There are two clocks supported in modern web browsers.

  • System Clock (Date.now() or new Date). The system clock is the ordinary time provided by the operating system. Using the system clock to timestamp events poses a risk: the user or operating system can adjust the clock at any time, for any reason, without any notice, to any value. The user might manually adjust the clock, for example, or the operating system might synchronize the clock to account for clock skew (e.g., NTP time sync). These adjustments can be large and non-monotonic, breaking assumptions that WebScience makes about timestamp proximity and ordering. A clock change during study execution could introduce subtle bugs or other unexpected behavior.
  • Shared Monotonic Clock (performance.timeOrigin + performance.now()). The W3C High Resolution Time recommendation specifies a shared monotonic clock. This clock should have the following properties:
    • strictly monotonic;
    • not subject to large or non-monotonic adjustments from any source;
    • consistent across cores, processes, threads, and globals down to the hardware level; and
    • synchronized to the system clock just once, on browser startup.

Our goal is to migrate WebScience and Rally studies to the shared monotonic clock, because it does not have clock change risks like the system clock. Unfortunately, browser implementations of High Resolution Time currently depart from the W3C recommendation in significant ways that prevent reliance on the shared monotonic clock. We will update this module as browsers correct their implementations.

Additional Notes

  • The High Resolution Time spec describes a shared monotonic clock (which must be used to generate performance.timeOrigin for each global) and per-global monotonic clocks (which tick for performance.now() and other uses of DOMHighResTimeStamp). Monotonic clocks on modern hardware are synchronized across cores, processes, and threads, so we treat performance.timeOrigin + performance.now() as the current time on the shared monotonic clock, even though the W3C spec doesn't quite say that.
  • Firefox and Chrome currently depart from the High Resolution Time spec in significant ways: performance.timeOrigin is sometimes set from the system clock rather than the shared monotonic clock, and performance.now() (and other uses of DOMHighResTimeStamp) do not tick during system sleep on certain platforms.
Source:
See:

Methods

(static) fromMonotonicClock(timeStamp, relativeToTimeOrigin) → {number}

Convert a timestamp on the shared monotonic clock to a timestamp on the standardized clock. Use this function only where strictly necessary, and where it can be used immediately after the timestamp on the monotonic clock. There is a risk that the system clock will have changed between the timestamp and now or that the monotonic clock was affected by an implementation bug.

Parameters:
Name Type Description
timeStamp number

A timestamp, in milliseconds since the epoch, on the shared monotonic clock.

relativeToTimeOrigin boolean

Whether the timestamp is relative to a time origin (e.g., a DOM event or Performance API timestamp), or the time origin has already been added to the timestamp (e.g., performance.timeOrigin or performance.timeOrigin + performance.now()).

Source:
Returns:

A timestamp, in milliseconds since the epoch, on the standardized clock.

Type
number
Examples
const monotonicTimeStamp = performance.timeOrigin;
const standardizedTimeStamp = webScience.timing.fromMonotonicClock(monotonicTimeStamp, false);
const monotonicTimeStamp = performance.timeOrigin + performance.now();
const standardizedTimeStamp = webScience.timing.fromMonotonicClock(monotonicTimeStamp, false);
const relativeMonotonicTimeStamp = performance.now();
const standardizedTimeStamp = webScience.timing.fromMonotonicClock(relativeMonotonicTimeStamp, true);

(static) fromSystemClock(timeStamp) → {number}

Convert a timestamp on the system clock to a timestamp on the standardized clock. Use this function only where strictly necessary, and where it can be used immediately after the timestamp on the system clock. There is a risk that the system clock will have changed between the timestamp and now.

Parameters:
Name Type Description
timeStamp number

A timestamp, in milliseconds since the epoch, on the system clock.

Source:
Returns:

A timestamp, in milliseconds since the epoch, on the standardized clock.

Type
number
Example
const systemTimeStamp = Date.now();
const standardizedTimeStamp = webScience.timing.fromSystemClock(systemTimeStamp);

(static) now() → {number}

Get the current time, in milliseconds since the epoch, using a standardized clock.

Source:
Returns:

The current time, in milliseconds since the epoch.

Type
number