Does JavaScript provide a high resolution timer?

Almost all modern browsers provide a high resolution timer. It's the "High Resolution Time" W3C standard: http://www.w3.org/TR/hr-time/#sec-DOMHighResTimeStamp.

It allows you to get a sub-millisecond accurate timestamp by calling window.performance.now(). This returns a time stamp in ms, but it is a float so you still get sub-millisecond resolution.

Very old browsers may implement a "prefixed" version of this standard, e.g. WebKit based browsers used to implement window.performance.webkitNow()

Here is some code you can use to get the the accurate timestamp when available and fallback to standard precision otherwise:

if (window.performance.now) {
    console.log("Using high performance timer");
    getTimestamp = function() { return window.performance.now(); };
} else {
    if (window.performance.webkitNow) {
        console.log("Using webkit high performance timer");
        getTimestamp = function() { return window.performance.webkitNow(); };
    } else {
        console.log("Using low performance timer");
        getTimestamp = function() { return new Date().getTime(); };
    }
}

getTimestamp();

Note that this getTimestamp() function does not return a value that represents the current date/time. The returned value can only be used to measure time-periods, by subtracting two different timestamps. E.g.

var t1 = getTimestamp();
//... some other code
var t2 = getTimestamp();
console.log("Time delta: " + (t2 - t1));

See @h3r3's answer—it is the correct answer.

Milliseconds are the best you can hope for in JavaScript. And, like you said, it isn't very accurate. See Stack Overflow question Microsecond timing in JavaScript.

timer.js purports to provide up to microsecond resolution, but it is only available for Google Chrome.

Update: timer.js does not support microsecond resolution. It just multiplies millisecond count by 1000.

Sorry, there isn't better news!


Instead of while (true)/setInterval, use recursive requestAnimationFrame. It will run smoother than timeout based animations. It provides timestamps if you need your animation to run at slower path.


As of now (February 25, 2013), the quality of high-performance times in Chrome 24 is pretty horrible.

var old = 0; 

for (var i=0; i<10; i++) {
    var t = window.performance.now(); 
    var d = t - old; 
    old = t; 
    console.log(t + ' += ' +d); 
}

outputs something like this:

609689.000000013 += 609689.000000013
609689.9999999441 += 0.9999999310821295
609689.9999999441 += 0
609689.9999999441 += 0
609689.9999999441 += 0
609690.9999999916 += 1.0000000474974513
609690.9999999916 += 0
609690.9999999916 += 0
609691.9999999227 += 0.9999999310821295
609691.9999999227 += 0

Which shows that

1) Sampling happens rarely

2) The precision is still around 1ms, not in the microsecond range.


Here's what your code should look like in JavaScript, so it doesn't block the user interface and doesn't use window.requestAnimationFrame which does not work cross-browser.

/* Called once, preload essential resources here. */
function init() {}

/* Updates game/animation state */
function update(time) {}

/* Updates screen graphics  */
function render(time) {}

window.onload = function()
{
    var time;
    var done = false;

    init();
    // Using setTimeout passing zero makes the animate function run
    // as soon as possible, but yielding first.
    setTimeout(animate, 0);

    function animate () {
        time = new Date();
        update(time);
        render(time);
        if (!done) {
            setTimeout(animate, 0);
        }
    }
}

A problem with this approach is that the animate() may get called more often than the screen gets updated (at 60 Hz it won't update more often than abot every 16 ms), causing extra rendering that never makes it to the screen. That's why you should stick with requestAnimationFrame if possible.