Skip to content

Performance and timers

Background

The Workers runtime supports a subset of the Performance API ↗, used to measure timing and performance, as well as timing of subrequests and other operations.

performance.now()

The performance.now() method ↗ returns timestamp in milliseconds, representing the time elapsed since performance.timeOrigin.

When Workers are deployed to Cloudflare, as a security measure to mitigate against Spectre attacks, APIs that return timers, including performance.now() ↗ and Date.now() ↗, only advance or increment after I/O occurs. Consider the following examples:

Time is frozen — start will have the exact same value as end.
const start = performance.now();
for (let i = 0; i < 1e6; i++) {
// do expensive work
}
const end = performance.now();
const timing = end - start; // 0
Time advances, because a subrequest has occurred between start and end.
const start = performance.now();
const response = await fetch("https://developers.cloudflare.com/");
const end = performance.now();
const timing = end - start; // duration of the subrequest to developers.cloudflare.com

By wrapping a subrequest in calls to performance.now() or Date.now() APIs, you can measure the timing of a subrequest, fetching a key from KV, an object from R2, or any other form of I/O in your Worker.

In local development, however, timers will increment regardless of whether I/O happens or not. This means that if you need to measure timing of a piece of code that is CPU intensive, that does not involve I/O, you can run your Worker locally, via Wrangler, which uses the open-source Workers runtime, workerd ↗ — the same runtime that your Worker runs in when deployed to Cloudflare.

performance.timeOrigin

The performance.timeOrigin ↗ API is a read-only property that returns a baseline timestamp to base other measurements off of.

In the Workers runtime, the timeOrigin property returns 0.