How to measure the execution time of a promise?

前端 未结 4 1838
迷失自我
迷失自我 2020-12-03 15:05

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

export class Profiler {
    public measureSyncFunc(fn: () => any): P         


        
相关标签:
4条回答
  • 2020-12-03 15:39

    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.

    0 讨论(0)
  • 2020-12-03 15:44

    If the functions you want to measure will always be synchronous there's really no need to involve promises.

    Since the function you want to test takes parameters you it's best to to wrap it in an arrow function in order to be able to call it with another context and not have to manage it's parameters yourself.

    Something simple like this will do just fine.

    function measure(fn: () => void): number {
        let start = performance.now();
        fn();
        return performance.now() - start;
    }
    
    function longRunningFunction(n: number) {
        for (let i = 0; i < n; i++) {
            console.log(i);
        }
    }
    
    let duration = measure(() => {
        longRunningFunction(100);
    });
    
    console.log(`took ${duration} ms`);
    

    If you want to measure the time it takes an async function (if it returns a promise) to resolve you can easily change the code to something like this:

    function measurePromise(fn: () => Promise<any>): Promise<number> {
        let onPromiseDone = () => performance.now() - start;
    
        let start = performance.now();
        return fn().then(onPromiseDone, onPromiseDone);
    }
    
    function longPromise(delay: number) {
        return new Promise<string>((resolve) => {
            setTimeout(() => {
                resolve('Done');
            }, delay);
        });
    }
    
    measurePromise(() => longPromise(300))
        .then((duration) => {
            console.log(`promise took ${duration} ms`);
        });
    

    Note: This solution uses the ES6 Promise, if you are using something else you might have to adapt it but the logic should be the same.

    You can see both examples working in the playground here.

    0 讨论(0)
  • 2020-12-03 15:46

    Don't use setInterval to count milliseconds (It's inaccurate, lags, drifts and has a minimum interval of about 4ms). Just get two timestamps before and after the execution.

    function measureASyncFunc(fn: () => Promise<any>): Promise<number> {
        const start = Date.now();
        return fn.catch(() => {}).then(() => {
            const end = Date.now();
            const elapsed = end-start;
            return elapsed;
        });
    }
    

    For higher accuracy, replace Date.now by performance.now.

    0 讨论(0)
  • 2020-12-03 15:48

    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)
    
    0 讨论(0)
提交回复
热议问题