我需要以毫秒为单位获得执行时间。
我最初在2008年提出了这个问题。当时被接受的答案是使用
new Date().getTime()
。然而,现在我们都同意使用标准的performance.now()
API更加合适。因此,我将接受的答案更改为这个答案。
我需要以毫秒为单位获得执行时间。
我最初在2008年提出了这个问题。当时被接受的答案是使用
new Date().getTime()
。然而,现在我们都同意使用标准的performance.now()
API更加合适。因此,我将接受的答案更改为这个答案。
在函数前使用console.time('这里加标签名')
,在函数后使用console.timeEnd('这里加标签名')
,这将会给你提供函数的运行时间。
const { performance, PerformanceObserver } = require('perf_hooks');
const measures = []
const obs = new PerformanceObserver(list => measures.push(...list.getEntries()));
obs.observe({ entryTypes: ['measure'] });
const getEntriesByType = cb => cb(measures);
const doSomething = val => {
performance.mark('beginning of the process');
val *= 2;
performance.mark('after multiplication');
performance.measure('time taken', 'beginning of the process', 'after multiplication');
getEntriesByType(entries => {
entries.forEach(entry => console.log(entry));
})
return val;
}
doSomething(4);
在这里尝试此处
最初的回答与服务器和客户端(Node或DOM)一起工作,使用Performance
API。
当您有许多小周期时很好用,例如在被调用1000次的函数中处理1000个数据对象,但您想要查看此函数中每个操作如何相加到总和。
因此,这个使用一个模块全局(单例)定时器。与类单例模式相同,只是使用起来稍微简单一些,但您需要将其放入单独的文件中,例如stopwatch.js
。
最初的回答
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];
}
};
示例JS代码
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)
{
"plugins": [
"transform-decorators-legacy"
]
}
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;
}
}
}
InitTime
与string
相关。
return Singleton.getInstance().initTime(label); // 返回初始化时间
return Singleton.getInstance().endTime(label); // 返回初始化和结束之间的总时间
注意:这是最简单的纯函数式ES6实现方法,不需要额外的变量,只需三行代码。处理同步和异步代码,因此不需要外部库,在JavaScript和Node JS中都可以使用,甚至可以用来测试API的延迟
// Create one-liner timer function
let [timer, timingMonitor] = [0, () => timer = !timer ? Date.now() : `${Date.now() - timer}ms`]
// Initiate timer
timingMonitor();
// Your code here
doSomething();
// End timer
console.log(timingMonitor());
// Console output: "102ms", for example
console.time("myTimer");
console.timeLog("myTimer");
console.timeEnd("myTimer");
您可以在MDN和Node.js documentation中了解更多信息。
适用于Chrome、Firefox、Opera和NodeJS。(不适用于Edge或Internet Explorer)。
基本的TypeScript示例,支持标记。调用start('something')
将开始计时,并且stop('something')
将结束计时并返回包含经过时间的格式化字符串。
/**
* Mark entries
*/
export const marks: { [id: string]: number } = {};
/**
* Start timing
*/
export const start = (id: string) => {
return Object.assign(marks, {[id]: Date.now() })[id]
}
/**
* Clear all
*/
export const clear = () => {
for (const id in marks) delete marks[id];
};
/**
* Stop timing and return formatted elapsed time
*/
export const stop = (id: string) => {
const ms = Date.now() - marks[id];
delete marks[id];
return ms > 1000
? `${(ms / 1000).toFixed(0)}s ${+ms.toFixed(0).slice(1)}ms`
: `${ms.toFixed(0)}ms`;
};
as
导入中相应地调用方法,例如:import * as time from './timer.js'
time.start('foo')
// do something
console.log('elapsed time: ' + time.stop('bar'))
如先前所述,请检查并使用内置计时器。但如果您想要或需要编写自己的计时器,这是我的建议:
//=-=|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}}}();
被接受的答案是错误的!
由于JavaScript是异步的,所以被接受的答案中变量end的值将会是错误的。
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循环的执行可能非常快,因此您可能无法看到结果是错误的。您可以使用一些请求代码进行测试:
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
performance.now()
在 Node 中无法使用。你可以使用new Date().getTime()
来代替,在 Node 中它能正常工作。 - Ryan WalkerDate.now()
,在node中也可以工作。 - f278f1b2