Measuring execution time more precisely in the Browser and Node.js

2 min read

This post is part of my Today I learned series in which I share all my learnings regarding web development.

Measuring how long things take in applications is important. In the Frontend world we have the Navigation Timing API, Resource Timing API and the User Timing API to gather precise metrics.

Additionally I find myself using the Date object to evaluate how long something takes very often.

const before = Date.now();
console.log(before);
// 1505722233092

//
// some code here
//

console.log(Date.now() - before); 
// 81736 -> time passed in ms

By using the Date.now function I'm able to get durations in milliseconds. It returns a UNIX timestamp.

The Date.now() method returns the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.

But what if I could get a bit more precise?

# More precise timestamps in the browser

In the browser world I could also use window.performance.now which returns a DOMHighResTimeStamp. A DOMHighResTimeStamp can be accurate up to 5 microseconds(µs). Wow!

window.performance.now can also be used in e.g. web or services workers. In the Window context the returned value is the time elapsed since navigationStart.

const before = window.performance.now();
console.log(before);
// 1381822.74

//
// some code here
//

console.log(window.performance.now() - before);
// 7335.410000000149 -> time passed in precise ms

But what about Node.js?

# More precise timestamps in Node.js

What I learned today is that there is also a function in Node.js that is called hrtime to get high resolution timings. The Node.js docs describe the functionality quite nicely and include a good code sample.

const NS_PER_SEC = 1e9;
const time = process.hrtime();
// [ 1800216, 25 ]

setTimeout(() => {
  const diff = process.hrtime(time);
  // [ 1, 552 ]

  console.log(`Benchmark took ${diff[0] * NS_PER_SEC + diff[1]} nanoseconds`);
  // benchmark took 1000000552 nanoseconds
}, 1000);

hrtime returns an array including the seconds and nanoseconds to an arbitrary time in the past. Wait what?

Yes, the whole purpose of hrtime is to gather information on intervals or durations. That's why it doesn't really matter what the point in time was.

Cool thing about this function is that it accepts the result of another hrtime time call as optional argument. This way I don't have to calculate the diff myself and that's really handy!

# Measuring as precise as possible

With these two functions I'm able to get very precise information on how long something takes in JavaScript and this can be helpful for benchmarking execution times.

And that's it, happy measuring. 📏

Edited: Manuel Ernst also wrote a tiny wrapper around hrtime which is worth having a look.

Edited: Marcin pointed out in the comments that console.time and console.timeEnd are also valid options to measure times if you don't need high resolution timings. 👍🏻

Load time