Skip to content

Back to blog

Curiosity

Why 1ms doesn't always mean 1ms

· 6 min

A millisecond looks like a precise, unambiguous unit, but the real precision of a timestamp read in code depends on the clock source behind it, which varies more than most people assume.

Illustration of a clock with a dashed hand

Resolution isn't the same as precision

A clock can report values formatted in milliseconds (like `Date.now()`) while the OS timer behind it only actually updates every few milliseconds, several consecutive reads can return the exact same value even as real time passes between them, hiding differences smaller than that update interval.

Monotonic clocks exist for a specific reason

Wall-clock time can jump backward, NTP sync, leap seconds, a manual clock change, so measuring elapsed time with wall-clock timestamps can produce negative or wildly wrong durations. Monotonic clocks (`performance.now()`, `System.nanoTime()`, `CLOCK_MONOTONIC`) exist specifically to never go backward, which is why they're the right tool for measuring durations, never for logging when something happened.

Jitter: why two measurements of the same code give different numbers

CPU frequency scaling, other processes competing for the same core, cache effects, garbage collector pauses in managed runtimes, all of it introduces noise into the measurement. A single measurement of a fast operation is nearly meaningless on its own; what matters is the distribution across many runs.

The practical consequence

When the duration you're measuring gets close to the clock's actual resolution, a ~1ms query on a clock that updates every ~15ms, for instance, don't trust the single number. Measure many iterations and look at the distribution, or switch to a higher-resolution monotonic source built exactly for this.