[whatwg] Timing API proposal for measuring intervals

PROBLEM

It is not possible to accurately measure time intervals using existing web
platform APIs, or to specify times at a given interval from the current
time.  Date.now() and DOM timestamps are inadequate for this purpose, see
<sectiontitle> below for reasons why this is so.

USE CASES

1.) When updating an imperative animation state from script, authors need to
know how much time has elapsed in the animation so far in order to properly
update the animation.

2.) When synchronizing imperative animation updates with audio, authors need
to know how much time has elapsed in the animation and in the audio sample's
progression and be able to schedule future audio cues to specific points in
the animation.

3.) When measuring the time that a given operation has taken (for example, a
network request or a application process), authors need to be able to
measure the amount of time elapsed from script.

ISSUES WITH EXISTING APIS

In ECMAScript the Date object is typically used for timing.  It is defined
(in ES-262 5th edition section 15.9.1.1) as representing milliseconds since
the unix epoch, Jan 1 1970 00:00:00 UTC, ignoring leap seconds.  DOM
timestamps are defined in a similar way, although it doesn't seem to specify
anything about leap seconds.  In practice, implementations depend on the
system clock for these APIs and are likely to use the same implementation
for both.  This poses a problem whenever the system clock is adjusted.  In
all implementations I tested, Date.now() varies whenever the system clock is
adjusted.  This means that, for example, the following snippet:

var start = Date.now();
dosomething();
window.alert(Date.now() - start);

may alert a positive number, negative number, or zero if the system clock is
adjusted in between the two calls to Date.now().  Similarly, timestamps from
a series of DOM events may be increasing, decreasing, or unchanging if the
system clock adjusts in between event dispatches.  System clock adjustments
are not as rare as you might thing, many systems are configured to receive
clock updates over the network via NTP or similar systems.  When developing
and implementing the navigation timing spec we ran in to many reported time
intervals from users in the wild that were bogus in one way or another,
either negative (easily detectable) or artificially inflated (very difficult
to detect).  I've put a simple test page up here:
http://webstuff.nfshost.com/timers.html.

Additionally, there's a practical concern that querying the system clock on
some systems is more expensive and/or less reliable than other timing APIs.
 On windows, for instance, GetSystemTimeAsFileTime() has a resolution of
~15.5ms, so browsers use a combination of GetSystemTimeAsFileTime() with
higher-resolution timing APIs like QueryPerformanceCounter() that provide
better resolution but are not affected by adjustments to the system clock.
 See http://drdobbs.com/windows/184416651?pgno=1 and
https://bugzilla.mozilla.org/show_bug.cgi?id=363258 for some background
information.

PROPOSAL

I propose that we add a new attribute to the Window interface that provides
a monotonic, uniformly increasing timestamp suitable for interval
measurements.

<bikeshed-topic>
partial interface Window {
  readonly attribute double monotonicTime;
};
</bikeshed-topic>

<bikeshed-topic>
I propose that monotonicTime be defined as the number of milliseconds
elapsed since the window creation.  There is likely to be no meaningful
relationship between the value exposed by this interval and a date and time
in the past (such as the unix epoch), so starting at zero seems a good at
choice as any.
</bikeshed-topic>

I do not believe we can change the meaning of Date.now() in ECMAScript since
the current behavior has existing for a very long time and is genuinely
useful when the author wants to know the system clock's current value, for
example in a calendar type application.

RELATIONSHIP TO EXISTING WORK, IMPLEMENTATION NOTES

The setTimeout() and setInterval() algorithms (
http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#timers)
implicitly depend on a uniformly monotonic clock in the various "wait for X
milliseconds" phase, since there is no allowance in this text for
adjustments to the system clock to change when the timer actually fires.
 All browsers except for WebKit ignore system clock changes for timer
scheduling, and the WebKit behavior is a bug which I plan to fix.

The Web Perf WG has run into similar issues and defined a monotonic clock as
part of the Navigation Timing API:
http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html#mono-clock.
 This clock is very similar to the above proposal but is not exposed
directly to authors.  I expect that implementations of the Navigation Timing
API would use the same mechanism to implement this proposal.

The proposed Web Audio API (
http://chromium.googlecode.com/svn/trunk/samples/audio/specification/specification.html#AudioContext-section)
exposes
a timestamp on the AudioContext interface that is defined to map to a
monotonic uniformly increasing hardware timestamp.

- James

Received on Thursday, 7 July 2011 18:15:11 UTC