How to measure the execution time of an asynchronous function in nodejs?
Asked Answered
N

3

7

I'm trying to get the execution/response time of an asynchronous function that executes inside a node-fetch operation, like the following

async function getEditedData() {      
       var a = await fetch(`https://api.example.com/resorce_example`);
       var b = await a.json();
       // Some aditional treatment of the object obtained (b)
       console.log("End of the asynchronous function")
}

I Used the library perf_hooks like this, but the execution time shows before

const hrtime = require ('perf_hooks').performance.now ;
var start = hrtime ();
   getEditedData();
var end   = hrtime ();
console.log (end - start);

I found the async_hooks library https://nodejs.org/api/perf_hooks.html#perf_hooks_measuring_the_duration_of_async_operations , but I can´t understand how it works. I am a basic in javascript/nodejs

Newmarket answered 3/4, 2020 at 19:8 Comment(2)
getEditedData().then(() => console.log(hrtime() - start))Autotoxin
await or .then().catch(). No different than calling any asynchronous function.Sheaves
P
3

You could simply store Date.now() in some variable and then check Date.now() when your Promise resolves (or rejects) and subtract to find the difference. For example:

const simulateSomeAsyncFunction = new Promise((resolve, reject) => {
  console.log('Initiating some async process, please wait...')
  const startTime = Date.now();

  setTimeout(() => {
    resolve(Date.now() - startTime);
  }, 3000);
});

simulateSomeAsyncFunction.then(msElapsed => {
  console.log(`Async function took ${msElapsed / 1000} seconds to complete.`);
});

Note: You could write code that achieves the same thing and appears to be synchronous by using await/async since that is just "syntactic sugar" built on top of Promises. For example:

const simulateSomeAsyncFunction = () => {
  console.log('Initiating some async process, please wait...');

  return new Promise((resolve, reject) => {
    setTimeout(resolve, 3000);
  });
};

// Await is required to be called within an async function so we have to wrap the calling code in an async IIFE
(async() => {
  const startTime = Date.now();

  await simulateSomeAsyncFunction();

  const msElapsed = Date.now() - startTime;

  console.log(`Async function took ${msElapsed / 1000} seconds to complete.`);
})();
Postgraduate answered 3/4, 2020 at 19:30 Comment(0)
A
3

If you expect to set the end after getEditedData() is completed, you actually need to await getEditedData(). Otherwise, you'll go right past it while it executes... asynchrnously.

Aggravate answered 3/4, 2020 at 19:12 Comment(0)
P
3

You could simply store Date.now() in some variable and then check Date.now() when your Promise resolves (or rejects) and subtract to find the difference. For example:

const simulateSomeAsyncFunction = new Promise((resolve, reject) => {
  console.log('Initiating some async process, please wait...')
  const startTime = Date.now();

  setTimeout(() => {
    resolve(Date.now() - startTime);
  }, 3000);
});

simulateSomeAsyncFunction.then(msElapsed => {
  console.log(`Async function took ${msElapsed / 1000} seconds to complete.`);
});

Note: You could write code that achieves the same thing and appears to be synchronous by using await/async since that is just "syntactic sugar" built on top of Promises. For example:

const simulateSomeAsyncFunction = () => {
  console.log('Initiating some async process, please wait...');

  return new Promise((resolve, reject) => {
    setTimeout(resolve, 3000);
  });
};

// Await is required to be called within an async function so we have to wrap the calling code in an async IIFE
(async() => {
  const startTime = Date.now();

  await simulateSomeAsyncFunction();

  const msElapsed = Date.now() - startTime;

  console.log(`Async function took ${msElapsed / 1000} seconds to complete.`);
})();
Postgraduate answered 3/4, 2020 at 19:30 Comment(0)
N
3

Starting with a simple async function -

const fakeAsync = async (value) => {
  const delay = 2000 + Math.random() * 3000 // 2 - 5 seconds
  return new Promise(r => setTimeout(r, delay, value))
}

fakeAsync("foo").then(console.log)

console.log("please wait...")

// "please wait..."
// "foo"

We could write a generic function, timeit. This is a higher-order function that accepts a function as input and returns a new function as output. The new function operates like a decorated version of the original -

const timeit = (func = identity) => async (...args) => {
  const t = Date.now()
  const result = await func(...args)
  return { duration: Date.now() - t, result }
}

// decorate the original
const timedFakeAsync = timeit(fakeAsync)

// call the decorated function
timedFakeAsync("hello").then(console.log)
timedFakeAsync("earth").then(console.log)

// { duration: 3614, result: "earth" }
// { duration: 4757, result: "hello" }

The timed version of our function returns an object, { duration, result }, that reports the runtime of our async function and the result.

Expand the snippet below to verify the results in your own browser -

const identity = x =>
  x

const timeit = (func = identity) => async (...args) => {
  const t = Date.now()
  const result = await func(...args)
  return { duration: Date.now() - t, result }
}

const fakeAsync = async (value) => {
  const delay = 2000 + Math.random() * 3000 // 2 - 5 seconds
  return new Promise(r => setTimeout(r, delay, value))
}

const timedFakeAsync = timeit(fakeAsync)

timedFakeAsync("hello").then(console.log)
timedFakeAsync("earth").then(console.log)

console.log("please wait...")

// "please wait..."
// { duration: 3614, result: "earth" }
// { duration: 4757, result: "hello" }
Nicholas answered 5/4, 2020 at 18:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.