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

Jul*_*s A 1057 javascript profiling

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

我最初在2008年问过这个问题.然后,接受的答案是使用新的Date().getTime()但是,我们现在都同意使用标准的performance.now() API更合适.因此,我正在改变对此问题的接受答案.

vsy*_*ync 1569

使用 performance.now():

var t0 = performance.now();

doSomething();   // <---- The function you're measuring time for 

var t1 = performance.now();
console.log("Call to doSomething took " + (t1 - t0) + " milliseconds.");
Run Code Online (Sandbox Code Playgroud)

NodeJs:需要导入performance该类


使用console.time:(非标准)(生活标准)

console.time('someFunction');

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

console.timeEnd('someFunction');
Run Code Online (Sandbox Code Playgroud)

注意:
传递给time()timeEnd()方法的字符串必须匹配
(使计时器按预期完成).

console.time() 单证:

  1. 有关的NodeJS文档
  2. MDN(客户端)文档

  • 它现在也得到Chrome开发者工具的支持. (23认同)
  • 是的,你可以做`totalTime + = console.timeEnd('timer')'并为每个计时器做 (6认同)
  • 你不需要在这两个语句之间执行函数吗?您现在可以测量定义它所需的时间,而不是执行它.如我错了请纠正我... (5认同)
  • 这是目前根据我的理解收集准确时间的最佳方式. (3认同)
  • 链接到有关此功能的MDN文章:https://developer.mozilla.org/en-US/docs/DOM/console.time (2认同)
  • 顺便说一句,如果您在Chrome中工作 - 请确保您没有无意中设置了错误的日志消息过滤器.timeEnd()将消息记录为"Debug"控制台消息.送我一点野鹅追逐...... (2认同)
  • @Squirrl - 这个线程是关于测量时间的,而不是“为什么”事情是这样的。这将是一个全新的讨论问题。简而言之,时间不同是因为您的 CPU 有周期,而不是每次运行命令时它都会为它投入相同数量的资源。 (2认同)
  • nodeJS中的Console.timeEnd返回`undefined`. (2认同)
  • 这是 performance.now() 的当前状态`时间戳实际上不是高分辨率的。为了减轻 Spectre 等安全威胁,浏览器目前会在不同程度上对结果进行四舍五入。(Firefox 在 Firefox 59 中开始四舍五入到 2 毫秒。)一些浏览器也可能会稍微随机化时间戳。在未来的版本中,精度可能会再次提高;浏览器开发人员仍在调查这些定时攻击以及如何最好地缓解它们。` (2认同)

Owe*_*wen 615

使用新的Date().getTime()

getTime()方法返回自1970年1月1日午夜以来的毫秒数.

恩.

var start = new Date().getTime();

for (i = 0; i < 50000; ++i) {
// do something
}

var end = new Date().getTime();
var time = end - start;
alert('Execution time: ' + time);
Run Code Online (Sandbox Code Playgroud)

  • 计时不准确,因为日期不适用于此功能.我会在这里大胆说你应该使用vsync的例子,如果你想要准确的计时.虽然它只适用于Chrome和Firefox ATM. (54认同)
  • @AshBlue,我们应该使用`window.performance.now`.请参见http://stackoverflow.com/a/15641427/632951 (29认同)
  • 请注意,您可以用+ new Date()替换getTime()调用:var start = + new Date(); //做东西警报("执行时间:"+(+新日期()) - 开始); (9认同)
  • 请注意,getMilliseconds()为您提供当前秒的毫秒分数.如果用getMilliseconds()替换getTime(),如果跨越一秒,则会得到负面结果. (9认同)
  • 按今天的标准,vsync的答案要正确得多,使用Date()可能会导致显示非常错误的结果,特别是在Windows平台上,结果可能会被四舍五入并覆盖到最近的15ms边界,从而产生奇怪的东西,如微小代码位上的0ms时序. (6认同)
  • 应该注意的是,在 NodeJS 中,控制台 `time()` 和 `timeEnd` 方法确实使用 `Date()` 对象。来源:https://github.com/joyent/node/blob/master/lib/console.js (2认同)
  • 事实上,使用 getTime() (至少在现代 JS 引擎中)是不必要的。两个“Date()”对象相减得到一个以毫秒为单位的数字。 (2认同)
  • 如果函数中有任何回调,则这不起作用。 (2认同)

Pac*_*ier 399

不要使用Date().参见下文.

用途performance.now():

<script>
var a = performance.now();
alert('do something...');
var b = performance.now();
alert('It took ' + (b - a) + ' ms.');
</script>
Run Code Online (Sandbox Code Playgroud)

它适用于:

  • IE 10 ++

  • FireFox 15 ++

  • Chrome 24 ++

  • Safari 8 ++

  • Opera 15 ++

  • Android 4.4 ++

  • 等等

console.time对你来说可能是可行,但它是非标准的§:

此功能是非标准功能,不符合标准.不要在面向Web的生产站点上使用它:它不适用于每个用户.有也可能实现之间不兼容大和行为可能会改变未来.

除了浏览器支持,performance.now似乎有可能提供更准确的时间,因为它似乎是简单的版本console.time.


<咆哮>此外,永远不要使用Date什么,因为它受到在"系统时间"的变化.这意味着当用户没有准确的系统时间时,我们得到无效结果 - 如"负时间" -

2014年10月,我的系统时钟乱了,猜猜是什么 ....我打开了Gmail,看到了我所有的一天的电子邮件" 0分钟前发送".我认为Gmail应该由Google的世界级工程师构建.......

(将你的系统时钟设置为一年前,然后转到Gmail,这样我们就可以大笑了.也许有一天我们会为JS 提供一个耻辱大厅Date.)

Google Spreadsheet的now()功能也受此问题的影响.

您将要使用的唯一时间Date是您希望向用户显示系统时钟时间.不是当你想要得到时间或测量任何东西.

  • 请注意,Safari尚不支持此功能:https://developer.mozilla.org/en-US/docs/Web/API/Performance.now() (6认同)
  • 正是我在寻找的!我希望能够一起添加几次,不能用控制台时间真正做到这一点. (3认同)
  • 我使用Firebug Profile和performance.now(),它们都运行良好.Performance.now()确认了我在Profile中的结果. (2认同)
  • 不适用于我最大的挂机,即IE7(企业客户).我不关心测量Chrome的性能,它总是闪电般快速. (2认同)
  • 这是一个比console.time()更好的方法. (2认同)

Nic*_*icJ 51

如果需要在本地开发计算机上获得函数执行时间,可以使用浏览器的分析工具或控制台命令,如console.time()console.timeEnd().

所有现代浏览器都内置了JavaScript分析器.这些分析器应该提供最准确的测量,因为您不必修改现有代码,这可能会影响函数的执行时间.

要分析您的JavaScript:

  • Chrome中,按F12并选择" 配置文件"选项卡,然后选择" 收集JavaScript CPU配置文件".
  • Firefox中,安装/打开Firebug,然后单击" 配置文件"按钮.
  • IE 9+中,按F12,单击脚本Profiler(取决于您的IE版本).

或者,在您的开发机器上,您可以使用console.time()和向代码添加检测console.timeEnd().这些功能在Firefox11 +,Chrome2 +和IE11 +中受支持,报告您启动/停止的定时器console.time(). time()将用户定义的计时器名称作为参数,timeEnd()然后报告自计时器启动以来的执行时间:

function a() {
  console.time("mytimer");
  ... do stuff ...
  var dur = console.timeEnd("myTimer"); // NOTE: dur only works in FF
}
Run Code Online (Sandbox Code Playgroud)

请注意,只有Firefox会返回timeEnd()通话中的已用时间.其他浏览器只是将结果报告给开发人员控制台:返回值为timeEnd()undefined.

如果您想在野外获得函数执行时间,则必须检测代码.你有几个选择.您可以通过查询来简单地保存开始和结束时间new Date().getTime():

function a() {
  var start = new Date().getTime();
  ... do stuff ...
  var end = new Date().getTime();
  var dur = end - start;
}
Run Code Online (Sandbox Code Playgroud)

但是,该Date对象仅具有毫秒级的分辨率,并且会受到任何OS系统时钟更改的影响.在现代浏览器中,有一个更好的选择.

更好的选择是使用高分辨率时间,也就是说window.performance.now(). 在两个重要方面now()比传统Date.getTime()方式更好:

  1. now()是一个亚毫秒分辨率的双精度,表示自页面导航开始以来的毫秒数.它返回小数中的微秒数(例如,1000.123的值是1秒和123微秒).

  2. now()是单调增加的.这很重要,因为Date.getTime()可能在后续呼叫中向前跳甚至向后跳.值得注意的是,如果OS的系统时间更新(例如原子钟同步),Date.getTime()也会更新. now()保证总是单调增加,因此它不受操作系统的系统时间的影响 - 它将始终是挂钟时间(假设你的挂钟不是原子的......).

now()几乎可以在任何地方使用new Date().getTime(),+ new Date和T Date.now()是.唯一的例外是,Datenow()时代不混合,如Date基于UNIX的时期(自1970年以来的毫秒数),而now()就是因为你的页面导航开始的毫秒数(所以它会比小得多Date).

以下是如何使用的示例now():

function a() {
  var start = window.performance.now();
   ... do stuff ...
  var end = window.performance.now();
  var dur = end - start;
}
Run Code Online (Sandbox Code Playgroud)

now()Chrome stable,Firefox 15+和IE10支持.还有几种填充剂.

用于测量野外执行时间的另一个选项是UserTiming.UserTiming的行为类似于console.time()console.timeEnd(),但它使用相同的高分辨率时间戳now()(因此您得到一个亚毫秒单调增加的时钟),并将时间戳和持续时间保存到PerformanceTimeline.

UserTiming具有标记(时间戳)和度量(持续时间)的概念.您可以根据需要定义任意数量,并在PerformanceTimeline上公开它们.

要保存时间戳,请致电mark(startMarkName).要获得自第一个标记以来的持续时间,您只需致电measure(measurename, startMarkname).然后,持续时间将与您的标记一起保存在PerformanceTimeline中.

function a() {
  window.performance.mark("start");
  ... do stuff ...
  window.performance.measure("myfunctionduration", "start");
}

// duration is window.performance.getEntriesByName("myfunctionduration", "measure")[0];
Run Code Online (Sandbox Code Playgroud)

UserTiming可在IE10 +和Chrome25 +中使用.还有一个polyfill(我写的).


Var*_*ina 33

要获得精确值,您应该使用Performance接口.现代版本的Firefox,Chrome,Opera和IE都支持它.以下是如何使用它的示例:

var performance = window.performance;
var t0 = performance.now();
doWork();
var t1 = performance.now();
console.log("Call to doWork took " + (t1 - t0) + " milliseconds.")
Run Code Online (Sandbox Code Playgroud)

Date.getTime()或者console.time()不适合测量精确的执行时间.如果您可以快速粗略估算,则可以使用它们.通过粗略估计,我的意思是你可以从实时转换15-60毫秒.

查看关于在JavaScript中测量执行时间的精彩文章.作者还提供了一些关于JavaScript时间准确性的链接,值得一读.


Ste*_*Mai 18

使用Firebug,启用Console和Javascript.点击个人资料 刷新.再次单击配置文件 查看报告.

  • 好建议,但显然只适用于FF.我们经常想比较浏览器的速度...... :-) (8认同)
  • Chrome现在也支持`console.time()`和`console.timeEnd()`. (4认同)
  • 在新的Firebuq上,他们将这个选项隐藏到菜单中,使用CTRL + SHIFT + P或console.profile(); console..profileEnd() (3认同)

Ach*_*ner 12

process.hrtime()在Node.js中可用- 它返回一个以纳秒为单位的值

var hrTime = process.hrtime()
console.log(hrTime[0] * 1000000 + hrTime[1] / 1000)
Run Code Online (Sandbox Code Playgroud)


kay*_*yz1 11

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]');
};
Run Code Online (Sandbox Code Playgroud)

基准

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

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

stopwatch.stop();

stopwatch.printElapsed();
Run Code Online (Sandbox Code Playgroud)

产量

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]
Run Code Online (Sandbox Code Playgroud)

performance.now()是可选的 - 只需将false传递给StopWatch构造函数.


Lev*_*rts 8

为了进一步扩展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;
};
Run Code Online (Sandbox Code Playgroud)

现在使用代码如下:

console.time('someFunction timer');

someFunction();

var executionTime = console.timeEndValue('someFunction timer');
console.log("The execution time is " + executionTime);
Run Code Online (Sandbox Code Playgroud)


这为您提供了更多可能性.您可以存储执行时间以用于更多目的,例如在方程式中使用它,或存储在数据库中,通过websockets发送到远程客户端,在网页上提供服务等.


Alo*_*wal 8

你也可以在这里使用add运算符

 var start = +new Date();
 callYourFunctionHere();
 var end = +new Date();
 var time = end - start;
 console.log('total execution time = '+ time + 'ms');
Run Code Online (Sandbox Code Playgroud)

  • @Bardelman 与 Number(new Date()) 完全一样。 (2认同)

alj*_*gom 8

这是计时函数的装饰器

let timed = (f) => (...args)=>{
    let start = performance.now();
    let ret = f(...args);
    console.log(`function ${f.name} took ${(performance.now()-start).toFixed(3)}ms`)
    return ret;   
}
Run Code Online (Sandbox Code Playgroud)

用法:

let test = ()=>{/*does something*/}
test = timed(test)   // turns the function into a timed function in one line
test()               // run your code as normal, logs 'function test took 1001.900ms' 
Run Code Online (Sandbox Code Playgroud)

如果您使用异步函数,您可以进行timed异步并await在 f(...args) 之前添加一个,这应该适用于那些。如果您希望一个装饰器同时处理同步和异步功能,则情况会变得更加复杂。


小智 8

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

  1. 使用 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');
    
    Run Code Online (Sandbox Code Playgroud)
  2. 这是最有效的方法: 使用 performance.now(),例如

    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");
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用 +(add operator) 或 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);
    
    Run Code Online (Sandbox Code Playgroud)

以下是将一元加号运算符应用于 Date 实例时发生的情况:获取相关 Date 实例的值将其转换为数字

注意:getTime()提供比一元 + 运算符更好的性能。


alj*_*gom 7

这是一个定时器功能。如果您想测量多个未嵌套的事物之间的时间:

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

与 类似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'
Run Code Online (Sandbox Code Playgroud)

如果您喜欢 中的蓝色console.time(),您可以使用此行代替

console.log(`${lap} in: %c${(performance.now()-timer.prev).toFixed(3)}ms`, 'color:blue');
Run Code Online (Sandbox Code Playgroud)


Vij*_*jay 7

使用此代码格式

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

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


use*_*559 6

只能使用一个变量:

var timer = -performance.now();

// Do something

timer += performance.now();
console.log("Time: " + (timer/1000).toFixed(5) + " sec.")
Run Code Online (Sandbox Code Playgroud)

timer/1000 -将毫秒转换为秒

.toFixed(5) -修剪多余的数字


Mx.*_*Mx. 5

由于console.time并且performance.now在某些主流浏览器(即IE10)中不受支持,我创建了一个利用最佳可用方法的超薄实用程序.但是,它缺少错误处理的错误处理(调用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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


And*_*rin 5

谢谢,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
Run Code Online (Sandbox Code Playgroud)

请注意,除了要测量的内容外,您不应该做任何事情(例如,console.log执行也需要时间并会影响性能测试)。

请注意,为了通过测量异步函数的执行时间,您应该var timeInMilliseconds = process.hrtime(t0)[1]/1000000;在回调中插入。例如,

var t0 = process.hrtime();
someAsyncFunction(function(err, results) {
var timeInMilliseconds = process.hrtime(t0)[1]/1000000;

});
Run Code Online (Sandbox Code Playgroud)


小智 5

它可能会帮助你.

var t0 = date.now(); doSomething(); var t1 = date.now(); console.log("Call to doSomething took approximate" + (t1 - t0)/1000 + " seconds.")

  • 虽然此代码片段可能会解决问题,但 [包括解释](//meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) 确实有助于提高帖子的质量。请记住,您是在为将来的读者回答问题,而那些人可能不知道您提出代码建议的原因。也请尽量不要在代码中添加解释性注释,这会降低代码和解释的可读性! (2认同)

Jon*_*een 5

几个月前,我整理了自己的例程,使用 Date.now() 对函数进行计时——尽管当时接受的方法似乎是 Performance.now()——因为性能对象尚不可用(构建-in) 在稳定的 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)
}
Run Code Online (Sandbox Code Playgroud)

笔记:

如果您打算在 Node.js 应用程序中使用该performance对象,则必须包含以下要求: const { performance } = require('perf_hooks')