How to measure the execution time of a promise?

Viewed 13689

I'm trying to write a function that measures the execution time of another function:

export class Profiler {
    public measureSyncFunc(fn: () => any): Promise<number> {
        return new Promise<number>((resolve, reject) => {
            let elapsed = 0;

            let intervalId = window.setInterval(() => {
                elapsed += 1; // this is never called
            }, 1);

            this.execFunc(fn)
                .then((result: any) => {
                    window.clearInterval(intervalId);
                    resolve(elapsed);
                });
        });
    }

    private execFunc(fn: () => any): Promise<any> {
        return new Promise<any>((resolve, reject) => {
            resolve(fn());
        });
    }
}

Then I use it like that:

let array = generateRandomArray(100000);

instance.measureSyncFunc(bubbleSort(array))
    .then((elapsed: number) => {
        console.log(`end session: ${elapsed} seconds`);
        resolve();
    });

The bubbleSort function is synchronous and it takes several seconds to complete. See code here:

The result in the console is "end session: 0 seconds" because the interval callback is never called.

Do you know how I can make it called ? Thank you very much guys !

5 Answers

Have a look at timeFnPromise and the related test cases.

  • target function is wrapped and executed when the wrapped function is called
  • appends fulfillment / rejection handler to the underlying Promise that returns the target functions return value as "ret" and the elapsed time as "elapsedTime"
  • supports arguments by passing them through to the target function

Samples Usage:

const wrappedFn = timeFnPromise(aFunctionThatReturnsAPromise)

wrappedFn()
.then((values)=>{
  const {ret, elapsedTime} = values
  console.log(`ret:[${ret}] elapsedTime:[${elapsedTime}]`)
})

Also available via NPM module jschest.

Here's a simple wrapper function I wrote. It returns a Promise (via the async keyword), and so you can just call it with your promise. I added the time value as a property to the response. If you cannot have that value in the response, then you would need to remove it afterwards.

const stopwatchWrapper = async (promise) => {
  const startTime = Date.now()
  const resp = await promise
  resp.executionTime = Date.now() - startTime
  return resp
}

const axiosPromise = stopwatchWrapper(axios(reqSelected))
const response = await axiosPromise
console.log(response.executionTime)

It would be good to clarify that the proposed approaches by toskv only work with the resolution of a single promise. If we want to use Promise.all() the time result it returns is wrong.

Here is an example with the code that toskv developed, but using Promise.all()

Measure with Promise.all()

If someone needs to measure the time it takes to execute each of the promises executed with a Promise.all() the approach that can be followed is to make use of the interceptors and do the time measurements there

Related