How to measure time taken by a function to execute
我需要以毫秒为单位获得执行时间。
I originally asked this question back in 2008. The accepted answer
then was to use new Date().getTime() However, we can all agree now
that using the standard performance.now() API is more
appropriate. I am therefore changing the accepted answer to this one.
使用性能。now():
1 2 3 4 5 6 | 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.") |
NodeJs : it is required to import theperformance class
使用console.time:(non-standard)(live standard)
1 2 3 4 5 | console.time('someFunction'); someFunction(); // Whatever is timed goes between the two"console.time" console.timeEnd('someFunction'); |
注意:传递给
console.time() documentations:NodeJS documentation regarding MDN (client-side) documentation
使用new date().gettime()。
The getTime() method returns the number of milliseconds since midnight of January 1, 1970.
前任。
1 2 3 4 5 6 7 8 9 | 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); |
不要使用日期()。在下面阅读。
使用
1 2 3 4 | var a = performance.now(); alert('do something...'); var b = performance.now(); alert('It took ' + (b - a) + ' ms.'); |
它的作用是:
IE 10 ++
火狐15 ++
铬24+
Safari 8 ++
歌剧15 +
Android 4.4 +
等
EDOCX1[3]可能对您是可行的,但它不是标准的§;:
This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.
除了浏览器支持之外,
另外,不要将
On Oct 2014, my system clock went haywire and guess what.... I opened Gmail and saw all of my day's emails"sent 0 minutes ago". And I'd thought Gmail is supposed to be built by world-class engineers from Google.......
(将您的系统时钟设置为一年前,然后转到Gmail,这样我们就可以好好地笑了。也许有一天,我们会为js
谷歌电子表格的
您使用
如果需要在本地开发机器上获得函数执行时间,您可以使用浏览器的分析工具,也可以使用控制台命令,如
所有现代浏览器都内置了javascript分析器。这些分析器应该提供最精确的度量,因为您不必修改现有的代码,这可能会影响函数的执行时间。
要分析您的javascript:
- 在Chrome中,按F12并选择配置文件选项卡,然后收集javascript CPU配置文件。
- 在firefox中,安装/打开firebug,然后单击profile按钮。
- 在IE 9+中,按F12,单击脚本或探查器(取决于您的IE版本)。
或者,在您的开发机器上,您可以使用
1 2 3 4 5 | function a() { console.time("mytimer"); ... do stuff ... var dur = console.timeEnd("myTimer"); // NOTE: dur only works in FF } |
请注意,只有firefox返回
如果您想在野外获得函数执行时间,则必须插入代码。你有几个选择。您只需查询
1 2 3 4 5 6 | function a() { var start = new Date().getTime(); ... do stuff ... var end = new Date().getTime(); var dur = end - start; } |
但是,
更好的选择是使用高分辨率时间,也就是说
下面是如何使用
1 2 3 4 5 6 | function a() { var start = window.performance.now(); ... do stuff ... var end = window.performance.now(); var dur = end - start; } |
在野外测量执行时间的另一个选项是用户计时。用户计时与
用户计时具有标记(时间戳)和度量(持续时间)的概念。您可以根据自己的需要定义任意一个,它们都会在PerformanceTimeline上公开。
要保存时间戳,您可以调用
1 2 3 4 5 6 7 | function a() { window.performance.mark("start"); ... do stuff ... window.performance.measure("myfunctionduration","start"); } // duration is window.performance.getEntriesByName("myfunctionduration","measure")[0]; |
用户计时在IE10+和Chrome25+中可用。还有一个polyfill可用(我写的)。
为了得到精确的值,应该使用性能接口。它在火狐、Chrome、Opera和IE的现代版本中得到了支持。下面是一个如何使用它的示例:
1 2 3 4 5 | var performance = window.performance; var t0 = performance.now(); doWork(); var t1 = performance.now(); console.log("Call to doWork took" + (t1 - t0) +" milliseconds.") |
在javascript中测量执行时间时,请查看这篇精彩的文章。作者还提供了几个有关javascript时间准确性的链接,值得一读。
使用firebug,同时启用控制台和javascript。单击配置文件。重新装入。再次单击配置文件。查看报告。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 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]'); }; |
基准
1 2 3 4 5 6 7 8 9 10 | var stopwatch = new StopWatch(); stopwatch.start(); for (var index = 0; index < 100; index++) { stopwatch.printElapsed('Instance[' + index + ']'); } stopwatch.stop(); stopwatch.printElapsed(); |
产量
1 2 3 4 5 6 | 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()是可选的-只需将false传递到秒表构造函数函数中。
process.hrtime()在node.js中可用-它以纳秒为单位返回值
1 2 | var hrTime = process.hrtime() console.log(hrTime[0] * 1000000 + hrTime[1] / 1000) |
为了进一步扩展vsync的代码,使其能够在nodejs中以值的形式返回timeend,可以使用这段代码。
1 2 3 4 5 6 7 8 | 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; }; |
现在使用如下代码:
1 2 3 4 5 6 | console.time('someFunction timer'); someFunction(); var executionTime = console.timeEndValue('someFunction timer'); console.log("The execution time is" + executionTime); |
这给了你更多的可能性。您可以将执行时间存储起来,以用于更多目的,例如将其用于公式中,或者存储在数据库中,通过WebSockets发送到远程客户机,在网页上提供服务等。
您也可以在这里使用添加运算符
1 2 3 4 5 | var start = +new Date(); callYourFunctionHere(); var end = +new Date(); var time = end - start; console.log('total execution time = '+ time + 'ms'); |
只能使用一个变量:
1 2 3 4 5 6 | var timer = -performance.now(); // Do something timer += performance.now(); console.log("Time:" + (timer/1000).toFixed(5) +" sec.") |
这可能对你有帮助。
doSomething();
var t1 = date.now();
console.log("Call to doSomething took approximate" + (t1 - t0)/1000 +" seconds.")
由于某些主要浏览器(即IE10)不支持
使用它并根据您的需要加以改进。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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); } } } |
谢谢,Achim Koellner,会扩大你的答案:
1 2 3 4 5 | 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 |
请注意,除了您想要测量的内容之外,您不应该做任何事情(例如,
注意,为了度量异步函数的执行时间,应该在回调中插入
1 2 3 4 5 | var t0 = process.hrtime(); someAsyncFunction(function(err, results) { var timeInMilliseconds = process.hrtime(t0)[1]/1000000; }); |
几个月前,我用date.now()编写了自己的例程,该例程对一个函数进行了多次运算,尽管当时接受的方法似乎是性能方法。now()。--因为性能对象在stable node.js版本中尚不可用(内置)。
今天我做了更多的研究,找到了另一种计时方法。因为我在node.js代码中也发现了如何使用它,所以我想在这里共享它。
下面结合W3C和node.js给出的示例:
1 2 3 4 5 6 7 8 | 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应用程序中使用
const { performance } = require('perf_hooks')
这是计时功能的装饰器
1 2 3 4 5 6 | 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; } |
用途:
1 2 3 | 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' |
如果您使用的是异步函数,那么您可以使
如果要测量多个非嵌套对象之间的时间间隔,可以使用以下方法:
1 2 3 4 | function timer(lap){ if(lap) console.log(`${lap} in: ${(performance.now()-timer.prev).toFixed(3)}ms`); timer.prev = performance.now(); } |
与console.time()类似,但如果不需要跟踪以前的计时器,则使用起来更容易。
如果您喜欢console.time()中的蓝色,可以改为使用此行
1 | console.log(`${lap} in: %c${(performance.now()-timer.prev).toFixed(3)}ms`, 'color:blue'); |
1 2 3 4 5 6 7 8 | // Usage: 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' |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | export default class Singleton { static myInstance: Singleton = null; _timers: any = {}; /** * @returns {Singleton} */ static getInstance() { if (Singleton.myInstance == null) { Singleton.myInstance = new Singleton(); } return this.myInstance; } initTime(label: string) { this._timers[label] = Date.now(); return this._timers[label]; } endTime(label: string) { const endTime = Date.now(); if (this._timers[label]) { const delta = endTime - this._timers[label]; const finalTime = `${label}: ${delta}ms`; delete this._timers[label]; return finalTime; } else { return null; } } } |
与
在我的例子中,我更喜欢使用@grammar-suger并用babel编译它。这个方法的问题是函数必须在对象内部。
样本JS代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | function timer() { return (target, propertyKey, descriptor) => { const start = Date.now(); let oldFunc = descriptor.value; descriptor.value = async function (){ var result = await oldFunc.apply(this, arguments); console.log(Date.now() - start); return result; } } } // Util function function delay(timeout) { return new Promise((resolve) => setTimeout(() => { resolve(); }, timeout)); } class Test { @timer() async test(timout) { await delay(timout) console.log("delay 1"); await delay(timout) console.log("delay 2"); } } const t = new Test(); t.test(1000) t.test(100) |
.babelrc(用于babel 6)
1 2 3 4 5 | { "plugins": [ "transform-decorators-legacy" ] } |
具有累积周期的秒表
使用服务器和客户机(节点或DOM),使用
所以这一个使用模块全局(单例)计时器。与类的singleton模式相同,只是使用起来简单一点,但是您需要将它放在一个单独的文件中,例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | const perf = typeof performance !=="undefined" ? performance : require('perf_hooks').performance; const DIGITS = 2; let _timers = {}; const _log = (label, delta?) => { if (_timers[label]) { console.log(`${label}: ` + (delta ? `${delta.toFixed(DIGITS)} ms last, ` : '') + `${_timers[label].total.toFixed(DIGITS)} ms total, ${_timers[label].cycles} cycles`); } }; export const Stopwatch = { start(label) { const now = perf.now(); if (_timers[label]) { if (!_timers[label].started) { _timers[label].started = now; } } else { _timers[label] = { started: now, total: 0, cycles: 0 }; } }, /** Returns total elapsed milliseconds, or null if stopwatch doesn't exist. */ stop(label, log = false) { const now = perf.now(); if (_timers[label]) { let delta; if(_timers[label].started) { delta = now - _timers[label].started; _timers[label].started = null; _timers[label].total += delta; _timers[label].cycles++; } log && _log(label, delta); return _timers[label].total; } else { return null; } }, /** Logs total time */ log: _log, delete(label) { delete _timers[label]; } }; |
实现这一目标有多种方法:
使用console.time
//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 the function here for which you have top measure the time
var v2 = performance.now();
console.log("total time taken ="+(v2-v1)+"milliseconds";
使用+(添加运算符)或GetTime()。
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()比一元+运算符提供更好的性能。
如前所述,检查并使用内置计时器。但如果你想或需要写你自己的,这是我的两分钱:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | //=-=|Source|=-=// /** * JavaScript Timer Object * * var now=timer['elapsed'](); * timer['stop'](); * timer['start'](); * timer['reset'](); * * @expose * @method timer * @return {number} */ timer=function(){ var a=Date.now(); b=0; return{ /** @expose */ elapsed:function(){return b=Date.now()-a}, start:function(){return a=Date.now()}, stop:function(){return Date.now()}, reset:function(){return a=0} } }(); //=-=|Google Advanced Optimized|=-=// timer=function(){var a=Date.now();b=0;return{a:function(){return b=Date.now()-a},start:function(){return a=Date.now()},stop:function(){return Date.now()},reset:function(){return a=0}}}(); |
编译成功了!
- 原始大小:219字节gzip(405字节未压缩)
- 编译大小:109字节gzip(187字节未压缩)
- 节省了50.23%的gzip大小(53.83%没有gzip
接受的答案是错误的!
因为javascript是异步的,所以接受答案的变量end的值是错误的。
1 2 3 4 5 6 7 8 9 | var start = new Date().getTime(); for (i = 0; i < 50000; ++i) { // JavaScript is not waiting until the for is finished !! } var end = new Date().getTime(); var time = end - start; alert('Execution time: ' + time); |
for的执行速度可能非常快,因此您看不到结果是错误的。您可以使用代码进行测试,并执行一些请求:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var start = new Date().getTime(); for (i = 0; i < 50000; ++i) { $.ajax({ url: 'www.oneOfYourWebsites.com', success: function(){ console.log("success"); } }); } var end = new Date().getTime(); var time = end - start; alert('Execution time: ' + time); |
所以警报将很快提示,但是在控制台中,您将看到Ajax请求正在继续。
您应该这样做:https://developer.mozilla.org/en-us/docs/web/api/performance.now