3

If the do work function was performing some operation, say, picking an item from queue and performing some operation. How would I get the execution times for doWork function over time. I want to find out how much time doWork takes to complete at an average.

Sample Code

function doWork () {
  return Promise.resolve({first: 'Tony', last: 'Starks'})
}

async function wrapper () {
  console.time('wrapper')
  const response = await doWork()
  console.timeEnd('wrapper')
  return response
}

Promise.all([
  wrapper(),
  wrapper(),
  wrapper()
]).then((result) => console.info(result))

Output

wrapper: 0.388ms
[ { first: 'Tony', last: 'Starks' },
  { first: 'Tony', last: 'Starks' },
  { first: 'Tony', last: 'Starks' } ]
(node:2749) Warning: No such label 'wrapper' for console.timeEnd()
(node:2749) Warning: No such label 'wrapper' for console.timeEnd()
8
  • It might be prudent to run the tests of your function end-to-end, otherwise each invocation will be "fighting" all the others for limited CPU time. It would make more sense to do performance testing one at a time, and stress testing the way you're doing now. Commented Jun 27, 2017 at 3:38
  • You are basically doing console.time('wrapper') thrice, then doing console.timeEnd('wrapper') thrice. Make the measurement of the parallel executing tasks by manually subtracting timestamps. Commented Jun 27, 2017 at 3:39
  • possible duplicate of How to measure the execution time of a promise?, unless your question specifically is why the console.time approach didn't work (please edit to make that clearer). Commented Jun 27, 2017 at 3:41
  • @PatrickRoberts Not sure I understand what you are trying to say. Commented Jun 27, 2017 at 4:04
  • @Bergi The code I posted is an over simplification of the actual code. I have built an offline process that performs a bunch of tasks. We are not sure how long each of the task takes. Ideally each of these tasks can be an AWS Lambda but without knowing how long it is taking we dont want to go the lambda way. Commented Jun 27, 2017 at 4:07

3 Answers 3

2

If you're just trying to get your console.time() and console.end() calls to work around your async function, you can generate a unique label each time you call console.time() and console.end() so that the measurement will still work when there are multiple calls in flight at the same time (since each call will then be using its own label):

let wrapperCntr = 0;

async function wrapper () {
  let cnt = wrapperCntr++;
  console.time('wrapper' + cnt);
  const response = await doWork();
  console.timeEnd('wrapper' + cnt);
  return response;
}
Sign up to request clarification or add additional context in comments.

7 Comments

Updated question with your suggestion.
@Perpetualcoder - Why would you update your question with my answer? That's not how things are supposed to work here. You can do several things with my answer such as upvote it, downvote it, comment on it, accept it, but copying it into your question is not one of them. Your question should stay what it originally was (with any needed clarification). Questions are questions, answers are answers and the two should not be merged here on stack overflow. Questions are NOT meant to be a running commentary on your latest thinking, incorporating what you've learned from answers.
Ok. Removed the updates. There was no reason to downvote. I had already upvoted it. However, it was not producing the results quite the way I wanted. But your solution got over the initial problem of the warnings thrown for labels going out of context.
@Perpetualcoder - What is the "results the way you wanted"? I had a hard time figuring out what you're really asking for beyond this.
I would like to know how much time (assuming the function was called 3 times), each call took. This method isolates each call because of the wrapperCntr but.. first call takes 0.6ms then it takes 2.6ms etc. I dont think this is the right behavior.
|
1

If you're hard-set on testing them in parallel, I recommend this approach:

function doWork () {
  return Promise.resolve({ first: 'Tony', last: 'Stank' })
}

async function wrapper (index) {
  console.time(index)
  const response = await doWork()
  console.timeEnd(index)
  return response
}

Promise.all(
  Array(3) // some big number
    .fill(wrapper)
    .map((wrapper, index) => wrapper(index))
).then((results) => console.info(results))

However, JavaScript is single-threaded. You're initializing 3 asynchronous functions in the same tick. They end up competing for CPU time on each asynchronous callback, which as you observed, causes undue timing delays.

Compare the times for above and below; below will be an order of magnitude faster because they are initialized in series and do not compete for CPU time:

function doWork () {
  return Promise.resolve({ first: 'Tony', last: 'Stank' })
}

async function wrapper ({ index, responses }) {
  console.time(index)
  responses.push(await doWork())
  console.timeEnd(index)
  return { index: ++index, responses }
}

Array(3) // some big number
  .fill(wrapper)
  .reduce(
    (promise, wrapper) => promise.then(wrapper),
    Promise.resolve({ index: 0, responses: [] })
  )
  .then(({ responses: results }) => console.info(results))

Comments

1

Related Question

Why not use the built-in performance package, which is available in node and the browser by default.

The following will work for multiple calls too...

async function timePromise(promiseFunction) {
  try {
    const begin = performance.now();
    await promiseFunction();
    const end = performance.now();
    const timeTaken_ms = end - begin;
    return timeTaken_ms;
  } catch (error) {
    console.error(error);
  }
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.