Measuring the Execution Time of Functions in JavaScript in a Graceful Way

Measuring the Execution Time of Functions in JavaScript in a Graceful Way

Daily short news for you
  • There is a rather interesting study that I came across: "Users never bother to read things they don't want to." (That's a bold statement, but it's more true than not. 😅)

    Don't believe it? I bet you've encountered situations where you've clicked on a button repeatedly and it doesn't respond, but in reality, it has displayed an error message somewhere. Or you've filled out everything and then when you hit the submit button, it doesn't go through. Frustrated, you scroll up or down to read and find out... oh, it turns out there's an extra step or two you need to take, right?

    It’s not far from the blog here. I thought that anyone who cares about the blog would click on the "Allow notifications" button just below the post. But the truth is, no one bothers to click it. Is it because they don't want to receive notifications? Probably not! I think it's because they just didn’t read that line.

    The evidence is that only when a notification pops up and takes up half the screen, or suddenly appears to grab attention, do they actually read it—and of course, it attracts a few more subscribers—something that was never achieved before.

    » Read more
  • A short article about the concepts of Functors, Applicatives, and Monads in functional programming that every time I read, I understand a little more 😅

    Functors, Applicatives, And Monads In Pictures

    » Read more
  • Rust is the time of its coming... It's "redefining" a whole bunch of things. Even the coreutils package containing basic Linux commands has been rewritten by it, and it runs on multiple platforms too 🫣

    uutils.github.io

    » Read more

Problem

During the development or operation of an application, unforeseen issues may arise. Once your application is released to the market, the number of users is likely to increase every day, resulting in a wide range of user behaviors and collected user data. These combinations can create various error scenarios that were not caught during the previous testing processes.

One of them may be that the API response suddenly becomes slow, even with a small number of users. When checking the feature causing this issue, it seems that you have discovered or are suspecting that a certain function is taking up a significant amount of processing time. To make sure you're right, of course, you need to measure how much time that function takes to execute.

There are many ways to identify which function is slowing down your system. APM applications with good control and diagnosis capabilities can timely alert you to issues. Some APM services have real-time data collection or alerting features if they detect that a function is taking too long to execute or if the API response time is too long. However, these services are not cheap, or if they are free, they come with limitations. That's why not everyone can afford to use APM. That's when you need a "cheaper" way that is completely free and accessible to everyone.

Measuring the Execution Time of Functions in JavaScript

Date.now(), console.time(), performance.now(), process.hrtime(), these are commonly used functions for measuring the time a function takes to execute. Basically, you just need to wrap the function you want to measure with these functions, and the execution time will be calculated.

The following example uses Date to measure the execution time by subtracting the two timestamps before and after the function is called.

const start = Date.now();

await functionToBeMeasured();

const end = Date.now();
console.log(`Execution time: ${end - start} ms`);

Alternatively, you can use console.time for a simpler approach:

console.time('executionFunctionToBeMeasured');

await functionToBeMeasured();

console.timeEnd('executionFunctionToBeMeasured');

console.time does not provide high accuracy. If you want sub-millisecond accuracy, you can use more powerful functions like performance.now() or process.hrtime() if you are using Node.js.

const start = performance.now();

await functionToBeMeasured();

const end = performance.now();
console.log(`Execution time: ${end - start} ms`);

After knowing how to measure the execution time, another issue arises: we need to wrap the function to be measured between the two time measurement functions. This causes code disruption in your project, requiring more modifications, making the code more cumbersome and difficult to control.

The idea here is to write a function to encapsulate the time measurement feature. The input is the function to be measured, and the output is the result of that function along with the execution time. Something like this:

calcExecuteTime(functionToBeMeasured);

Sometimes, functionToBeMeasured takes arguments, so let's make a slight modification:

calcExecuteTime(() => functionToBeMeasured(arg1, arg2...));

If functionToBeMeasured uses this, add a context parameter to receive this from the caller:

calcExecuteTime(context, () => functionToBeMeasured(arg1, arg2...));

Lastly, it is a good idea to add a name parameter to identify where the function is called from:

calcExecuteTime(name, context, () => functionToBeMeasured(arg1, arg2...));

The calcExecuteTime function can look like this:

const calcExecuteTime = async (name, context, fn) => {
  const start = process.hrtime();
  const result = await fn.call(context);
  const stop = process.hrtime(start);
  const executionTime = (stop[0] * 1e9 + stop[1]) / 1e9;
  console.log(`${name} execution time: ${executionTime}s`);
  return result;
};

Now let's try calling the function:

calcExecuteTime("Execute ToBeMeasured", this, () => functionToBeMeasured(arg1, arg2...));
// Execute ToBeMeasured execution time: 0.000178s

You can also modify the function according to your needs, for example, instead of logging the execution time using console.log, you can log it to somewhere else. Or enhance the function by adding a toggle flag to enable/disable the measuring feature.

References:

Premium
Hello

5 profound lessons

Every product comes with stories. The success of others is an inspiration for many to follow. 5 lessons learned have changed me forever. How about you? Click now!

Every product comes with stories. The success of others is an inspiration for many to follow. 5 lessons learned have changed me forever. How about you? Click now!

View all

Subscribe to receive new article notifications

or
* The summary newsletter is sent every 1-2 weeks, cancel anytime.
Author

Hello, my name is Hoai - a developer who tells stories through writing ✍️ and creating products 🚀. With many years of programming experience, I have contributed to various products that bring value to users at my workplace as well as to myself. My hobbies include reading, writing, and researching... I created this blog with the mission of delivering quality articles to the readers of 2coffee.dev.Follow me through these channels LinkedIn, Facebook, Instagram, Telegram.

Did you find this article helpful?
NoYes

Comments (1)

Leave a comment...
Avatar
Tuan Nguyen1 year ago
Thử chạy cái hàm đó trong 1_000_000 rồi tính trung bình sau đó đem so với chạy cái hàm đó 1 lần. Kết quả sẽ bất ngờ đó. Đó là cơ chế của node
Reply
Avatar
Xuân Hoài Tống1 year ago
Bạn ơi đó là cơ chế gì vậy ạ?