Wingbeat

How finely can a web page tell time? Browsers blur their clocks on purpose, because precise timing is how a page can learn what it should not. This page measures the blur, and the ways around it, on your device.

Measuring…

The page's clock

Read as fast as it can be, performance.now() stands still, then jumps. Chrome rounds it to 100 µs, or to 5 µs on a cross-origin isolated page like this one; other browsers have rules of their own.

The steps are the clock; the dashed line is time as it really passed.

A clock made from a counter

A blurred clock is easy to sharpen: a second thread counts as fast as it can in memory the page shares, and the page reads the count. That finer clock is what attacks like Spectre need to read memory they should not, so browsers share memory only with pages that are cross-origin isolated: pages that load nothing from other sites without their consent, and so have nothing of theirs in the same process to steal.

The screen's beat

Animation frames come when the screen is ready for the next picture: two seconds of them, each bar the time since the one before. Late ones are coloured.

How soon code can run again

A timeout of zero is not zero. Once timeouts nest more than five levels deep, the HTML standard lets browsers hold each one to at least 4 ms; some wait longer before they start. The cells show each nested call, the held ones marked.

    While the tab is hidden

    A ticker here means to run every 100 ms. Switch to another tab for ten seconds or so, then come back: browsers slow the timers of pages you cannot see, to save power. Shaded: hidden. Coloured: where the ticker went quiet (a short stretch while measuring is the measuring itself, which keeps the page busy).

    What it shows, honestly

    Every number here was measured just now, in this tab, and depends on the browser, the device, how busy it is and whether it runs on battery. Run it again and some will change. None is sent anywhere: the page makes no requests after it loads, and keeps nothing.

    The counter clock runs a second thread flat out for a quarter of a second, then stops. It reads nothing it should not: it only shows why browsers are careful with shared memory. This page can have it because it is cross-origin isolated, like every page on these labs.