Javascript: Accurate timing is (almost) here

If you’ve ever tried to optimize or locate a bottleneck in your Javascript code you’ve most likely ended up using Date().getTime(). As this function returns the number of milliseconds since the 1st of January, 1970 we can easily determine the total run time of the code we wish to test by taking two readings, one immediately prior to the code to be tested and and one immediately after. A simple subtraction will then give us the total run time in milliseconds:


var start, end;

start = (new Date()).getTime();

// Run a test

end = (new Date()).getTime();

alert(end - start);

While this is easy to use and consistently implemented across browsers it has a three flaws that make it less than ideal for benchmarking – the value returned is an integer so it’s useless for timing anything that takes less than a millisecond, it’s derived from the system clock which may be unstable or subject to adjustment and, depending on the operating system and browser, can be significantly wrong.

With the recent release of Google Chrome 20 to beta we now have the opportunity to use a new, more reliable and more precise timer – High Resolution Time a.k.a.  performance.now. More specifically, we can use the Chrome, vendor-prefixed, version – performance.webkitNow.

As performance.webkitNow returns the number of milliseconds since the navigationStart of the page and is not tied to the system clock we get more reliable timings. Better still, it returns the elapsed time as a double with microseconds in the fractional part, allowing us to have more accurate, sub-millisecond, timings.

If we rewrite the previous example to use High Resolution Time instead of Date().getTime() our code would be:


var start, end;

start = window.performance.webkitNow();

// Run a test

end = window.performance.webkitNow();

alert(end - start);

Running this example would give us results such as 0.005999987479299307 whereas our original, Date-based, example consistently returned zero.

Of course, it’s never so simple. This will work fine in Chrome 20 Beta but will error in all other browsers (and earlier versions of Chrome). To allow for other, as yet to be released, vendor-prefixed versions and to be usable today we must create a small shim function:

 var now = (function() {

// Returns the number of milliseconds elapsed since either the browser navigationStart event or
// the UNIX epoch, depending on availability.
// Where the browser supports 'performance' we use that as it is more accurate (microsoeconds
// will be returned in the fractional part) and more reliable as it does not rely on the system time.
// Where 'performance' is not available, we will fall back to Date().getTime().

var performance = window.performance || {};

performance.now = (function() {
return performance.now    ||
performance.webkitNow     ||
performance.msNow         ||
performance.oNow          ||
performance.mozNow        ||
function() { return new Date().getTime(); };
})();

return performance.now();

});   

This will use the “official” performance.now, if it is available. If not it will try each of the vendor prefixes, then ultimately fall back to Date().getTime(), allowing for all eventualities now or in the near future. Using this function is no more difficult that our previous examples:


var start, end;

start = now();

// Run a test

end = now();

alert(end - start);

 

You can try out this function on jsFiddle or grab it from Gist or Snipplr.

 

More:

4 thoughts on “Javascript: Accurate timing is (almost) here

  1. It’s as accurate as we can be in Javascript at the moment and a lot more accurate and usable than what was available previously (i.e. Date()).getTime()). For my purposes, which is measuring relative performance, it’s good enough.

    Is it perfect across all browsers? No, which is why the post is titled “Accurate timing is (almost) here”.

    If you have a better approach that I can use now, I’d love to hear about it.

  2. “the value returned is an integer so it’s useless for timing anything that takes less than a millisecond, it’s derived from the system clock which may be unstable or subject to adjustment and, depending on the operating system and browser, can be significantly wrong” … “As performance.webkitNow returns the number of milliseconds since the navigationStart of the page and is not tied to the system clock we get more reliable timings.”

    What do you mean that it’s not derived from the system clock? The system clock is the core time-keeping facility of a computer. It’s literally the device that the processor uses to count the number of cycles it makes per second. Window.performance.now() is, in fact, reliant on the system clock. It’s more accurate only because it provides a float rather than an integer, giving us a measure of microseconds (which the system clock provides) instead of the milliseconds that we were previously limited to in JavaScript.

  3. Have to say, this was perfect for what was needed. Thank you very much for the more accurate time measurements, I appreciate it!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s