-->

How to get microsecond timings in JavaScript since

2019-02-13 16:49发布

问题:

The situation

When writing high-performance JavaScript code, the standard profiling tools offered by Chrome et al are not always sufficient. They only seem to offer function-level granularity and it can be quite time-consuming to drill down and find the information I need.

In .NET the StopWatch class gives me exactly what I need: sub-microsecond resolution timing of arbitrary pieces of code.

For JavaScript performance.now() used to be a pretty good way to measure performance, but in response to Spectre and Meltdown all major browsers have reduced the resolution down to not even a millisecond.

To quote MDN on performance.now():

The timestamp is not actually high-resolution. To mitigate security threats such as Spectre, browsers currently round the result to varying degrees. (Firefox started rounding to 2 milliseconds in Firefox 59.) Some browsers may also slightly randomize the timestamp. The precision may improve again in future releases; browser developers are still investigating these timing attacks and how best to mitigate them.

The problem

I need microsecond precision timings. At the time of writing, browsers don't seem to offer any options or flags to disable these security measurements. Maybe I'm googling the wrong terms but the only articles I come across are explanations of the security problems and how these mitigations address them.

I'm not interested in the security aspect here - I'm benchmarking performance-critical pieces of JavaScript code on my own machine and the only thing I care about is that I get as accurate measurements as possible with as little effort as possible.

Existing workarounds

Two options come to mind:

  1. Install an older version of a browser that doesn't have these mitigations implemented

I'd have to dedicate an old version of FireFox to benchmarking, and a new version of Chrome to browsing for example. That's not practical since I need to test in all browsers (and preferably also benchmark in all browsers). Also, new optimizations are not implemented in old browsers so the benchmarks would be potentially useless.

  1. Implement a custom timer using WebWorkers

I've seen various older blog posts on this but none of them seem to achieve the high precision that I need (after all, there used to be performance.now() for that).

The question

How do I get an effectively pre-Spectre performance.now() without having to resort to older browser versions, Virtual Machines and such?

Are there any coding techniques or libraries in JavaScript that achieve microsecond precision?

Are there any options or flags for the 3 aforementioned browsers that disable these security measures?

I'm ultimately looking for a way to accurately measure the relative performance of different pieces of code compared to one another - so if there is a solution that gives me ticks, rather than microseconds, that would be acceptable too as long as it's accurate and works across browsers.

回答1:

Firefox does have a config setting called privacy.reduceTimerPrecision that disables the Spectre mitigation. You can switch it to false using Firefox's about:config page (type about:config into the address bar).

Figured this out via a hint on MDN.