如何测量函数执行所需的时间

1722

我需要以毫秒为单位获得执行时间。

我最初在2008年提出了这个问题。当时被接受的答案是使用 new Date().getTime()。然而,现在我们都同意使用标准的performance.now() API更加合适。因此,我将接受的答案更改为这个答案。


5
通常,说明您在执行时间方面想要实现的目标可能比仅回答问题更有用。现在,使用Firebug或Chrome Dev工具中的Profiling通常是查找占用CPU资源的代码的更好方法。 - oligofren
16
performance.now() 在 Node 中无法使用。你可以使用 new Date().getTime() 来代替,在 Node 中它能正常工作。 - Ryan Walker
2
@RyanWalker或者更简单的Date.now(),在node中也可以工作。 - f278f1b2
2
@oligofren - 有时候你可能想要捕获这些数据。我有一个情况,我正在将它写入indexedDB。 - ThomasRones
1
我想知道是否有最新的文档(例如在2020/201)表明在Node中performance.now()比Date.now()更好? - Qiulang
对于一个可以用于函数的一行代码,使它们在每次运行时记录其执行时间,请查看下面的答案 https://dev59.com/3XRC5IYBdhLWcg3wYf8p#52286301。它将计时逻辑封装到一个装饰器中,以便根据需要将其“包装”到函数中。 - aljgom
30个回答

13
var StopWatch = function (performance) {
    this.startTime = 0;
    this.stopTime = 0;
    this.running = false;
    this.performance = performance === false ? false : !!window.performance;
};

StopWatch.prototype.currentTime = function () {
    return this.performance ? window.performance.now() : new Date().getTime();
};

StopWatch.prototype.start = function () {
    this.startTime = this.currentTime();
    this.running = true;
};

StopWatch.prototype.stop = function () {
    this.stopTime = this.currentTime();
    this.running = false;
};

StopWatch.prototype.getElapsedMilliseconds = function () {
    if (this.running) {
        this.stopTime = this.currentTime();
    }

    return this.stopTime - this.startTime;
};

StopWatch.prototype.getElapsedSeconds = function () {
    return this.getElapsedMilliseconds() / 1000;
};

StopWatch.prototype.printElapsed = function (name) {
    var currentName = name || 'Elapsed:';

    console.log(currentName, '[' + this.getElapsedMilliseconds() + 'ms]', '[' + this.getElapsedSeconds() + 's]');
};

基准测试

var stopwatch = new StopWatch();
stopwatch.start();

for (var index = 0; index < 100; index++) {
    stopwatch.printElapsed('Instance[' + index + ']');
}

stopwatch.stop();

stopwatch.printElapsed();

输出

Instance[0] [0ms] [0s]
Instance[1] [2.999999967869371ms] [0.002999999967869371s]
Instance[2] [2.999999967869371ms] [0.002999999967869371s]
/* ... */
Instance[99] [10.999999998603016ms] [0.010999999998603016s]
Elapsed: [10.999999998603016ms] [0.010999999998603016s]

performance.now()是可选的 - 只需在StopWatch构造函数中传递false参数即可。


11

有多种方法可以实现这个目标:

  1. using console.time

    console.time('function');
    //run the function in between these two lines for that you need to 
    //measure time taken by the function. ("ex. function();")
    console.timeEnd('function');
    
  2. this is the most efficient way : using performance.now(), e.g.

    var v1 = performance.now();
    //run the function here for which you have top measure the time 
    var v2 = performance.now();
    console.log("total time  taken = "+(v2-v1)+"milliseconds");
    
  3. use +(add operator) or getTime()

    var h2 = +new Date(); //or
    var h2 = new Date().getTime();
    for(i=0;i<500;i++) { /* do something */}
    var h3 = +new Date();   //or 
    var h3 = new Date().getTime();
    var timeTaken = h3-h2;
    console.log("time ====", timeTaken);
    

当您对日期实例应用一元加操作符时,会发生以下情况: 获取相关日期实例的值 将其转换为数字

注意:getTime() 比一元加操作符具有更好的性能。


10

为了进一步扩展vsync的代码,使其能够以NodeJS中返回timeEnd作为值,请使用以下简短的代码片段。

console.timeEndValue = function(label) { // Add console.timeEndValue, to add a return value
   var time = this._times[label];
   if (!time) {
     throw new Error('No such label: ' + label);
   }
   var duration = Date.now() - time;
   return duration;
};
现在像这样使用代码:
console.time('someFunction timer');

someFunction();

var executionTime = console.timeEndValue('someFunction timer');
console.log("The execution time is " + executionTime);


这样做会给你带来更多的可能性。你可以将执行时间存储起来,以便将来用于诸如方程计算、存储在数据库中、通过WebSockets发送到远程客户端、提供在网页上等多种用途。


7

这可能会对你有所帮助。

var t0 = Date.now(); 做一些事情(); var t1 = Date.now(); console.log("调用doSomething花费了约" + (t1 - t0)/1000 + "秒。")


3
虽然这段代码片段可能解决了问题,但是包括解释真的有助于提高您的帖子质量。请记住,您正在回答未来读者的问题,而那些人可能不知道您提出代码建议的原因。请尽量避免在代码中添加过多的解释性注释,这会降低代码和解释的可读性! - Filnor

7

这是一个计时器函数。如果您想测量不嵌套的多个事物之间的时间:

function timer(lap){ 
    if(lap) console.log(`${lap} in: ${(performance.now()-timer.prev).toFixed(3)}ms`); 
    timer.prev = performance.now();
}

console.time()类似,但如果您不需要跟踪以前的计时器,则使用更容易。
用法:
timer()              // set the start
// do something 
timer('built')       // logs 'built in: 591.815ms'
// do something
timer('copied')      // logs 'copied in: 0.065ms'
// do something
timer('compared')    // logs 'compared in: 36.41ms'

如果您喜欢console.time()函数中的蓝色颜色,则可以使用以下代码行代替。
console.log(`${lap} in: %c${(performance.now()-timer.prev).toFixed(3)}ms`, 'color:blue');

注意!对于 NodeJS,您需要导入 performanceconst { performance } = require('perf_hooks'); - Daniel Habenicht

6

使用此代码格式。

const startTime =new Date().getTime();

//do something 
const endTime = new Date().getTime();
console.log(`time taken ${(endTime - startTime)/1000} seconds`);

6

由于某些主要浏览器(如IE10)不支持console.timeperformance.now,因此我创建了一个轻巧的实用程序,利用了最佳可用方法。但是,它缺乏错误处理功能,无法处理错误的用法(对未初始化的计时器调用End())。

请随意使用并改进它。

Performance: {
    Timer: {},
    Start: function (name) {
        if (console && console.time) {
            console.time(name);
        } else if (window.performance.now) {
            this.Timer[name] = window.performance.now();
        } else {
            this.Timer[name] = new Date().getTime();
        }
    },
    End: function (name) {
        if (console && console.time) {
            console.timeEnd(name);
        } else {
            var result;
            if (window.performance.now) {
                result = window.performance.now() - this.Timer[name];
            } else {
                result = new Date().getTime() - this.Timer[name];
            }
            console.log(name + ": " + result);
        }
    }
}

5
几个月前,我编写了自己的程序来计时一个函数,使用的是Date.now()方法,尽管当时接受的方法似乎是performance.now(),因为性能对象在稳定的Node.js版本中还没有可用(内置)。
今天我进行了更多的研究,发现了另一种计时方法。由于我也发现了如何在Node.js代码中使用它,所以我想在这里分享一下。
以下内容是从w3cNode.js给出的示例中组合而成的:
function functionTimer() {
    performance.mark('start')
    functionToBeTimed()
    performance.mark('end')
    performance.measure('Start to End', 'start', 'end')
    const measure = performance.getEntriesByName('Start to End')[0]
    console.log(measure.duration)
}

注意:

如果您打算在Node.js应用程序中使用performance对象,则必须包括以下要求:

const { performance } = require('perf_hooks')

我认为在这种情况下你不需要使用 performance.mark('end') - kofifus
文档:性能测量API - Henke

4

感谢Achim Koellner的回答,我稍微扩展一下:

var t0 = process.hrtime();
//Start of code to measure

//End of code
var timeInMilliseconds = process.hrtime(t0)[1]/1000000; // dividing by 1000000 gives milliseconds from nanoseconds

请注意,除了您要测量的内容以外,不应该执行任何其他操作(例如,console.log也需要时间来执行,并会影响性能测试)。
请注意,为了测量异步函数的执行时间,您应该在回调函数中插入var timeInMilliseconds = process.hrtime(t0)[1]/1000000;。例如,
var t0 = process.hrtime();
someAsyncFunction(function(err, results) {
var timeInMilliseconds = process.hrtime(t0)[1]/1000000;

});

3

在性能方面

NodeJs: 需要导入performance类

var time0 = performance.now(); // Store the time at this point into time0

yourFunction();   // The function you're measuring time for 

var time1 = performance.now(); // Store the time at this point into time1

console.log("youFunction took " + (time1 - time0) + " milliseconds to execute");

使用 console.time

console.time('someFunction');

someFunction(); // Whatever is timed goes between the two "console.time"

console.timeEnd('someFunction');

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接