javascript - 如何估计一个函数来执行所占用的时间

  显示原文与译文双语对照的内容

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

时间:

使用 Date(). getTime()

getTime() 方法返回从 1年午夜开始的毫秒数,1970.

示例


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);

或者,getMilliseconds() 将给出当前日期对象的毫秒。

你可以使用 console.time : ( non-standard )


console.time('someFunction');

someFunction();//run whatever needs to be timed in between the statements

console.timeEnd('someFunction');

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


更新

你可以使用标准的 performance.now(),比如:


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

不使用 Date() 。请阅读下面的内容。

使用 performance.now() :


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

它适用于:

  • IE 10 + +

  • Firefox 15 + +

  • Chrome 24 + +

  • Safari 8 + +

  • Opera 15 + +

  • Android 4.4 + +

  • 等,等等

console.time 可能可行的,但 non-standard § :

这里功能是non-standard并且不在标准轨道上。 不要在面向站点的生产站点上使用它: 它对每个用户都不起作用。 有也可能大之间的不兼容性实现和行为在未来可能会改变。

似乎除了浏览器支持, performance.now 潜在提供更准确的时间,因为它似乎 console.time的bare-bones版本。


<咆哮> 也永远不要使用 Date 任何"系统时间"因为它是受变化。 这意味着我们会无效的结果 —like"负计时"—当用户没有一个精确的系统时间:

2014年月, 我的系统时钟三丈,猜猜 。 我打开邮箱,看到所有"发送 0分钟前"我的邮件的一天。 我认为Gmail应该由谷歌的世界级工程师构建。。

( 将你的系统时钟设到一年前,然后转到 Gmail,这样我们都可以很好的欢笑。 也许有一天我们会有一个大厅耻辱 JS Date 。)

谷歌电子表格的now() 函数也存在这个问题。

唯一一次你将使用 Date 是当你想要显示用户系统时钟时间。 当你想 或衡量任何东西。

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

所有现代浏览器都内置了JavaScript分析器。 这些分析器应该给出最精确的度量,因为你不必修改现有代码,这可能会影响函数时间的执行。

要配置你的JavaScript:

  • Chrome, 按 F12选择配置文件选项卡,然后收集javascriptcpu配置文件。
  • Firefox 中,安装/打开 Firebug,并单击 。 按钮。
  • IE 9 +, 按 F12,点击脚本或者分析器 ( 取决于你的IE 版本) 。

或者,开发机器上,你可以向代码中添加仪器与 console.time()console.timeEnd() 。 这些函数,在 Firefox11+,Chrome2+和IE11+中支持,报告你通过 console.time() 启动/停止的计时器。 time() 将user-defined计时器名称作为参数,然后 timeEnd() 报告执行时间,因为计时器启动:


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

注意,只有 Firefox 在 timeEnd() 调用中返回经过的时间。 其他浏览器只是向开发人员控制台报告结果: timeEnd()的返回值未定义。

如果你想执行时间在野外函数,你将不得不仪器代码。 你有几个选项。 你可以通过查询 new Date().getTime() 来简单地保存开始时间和结束时间:


function a() {
 var start = new Date().getTime();
. . . do stuff.. .
 var end = new Date().getTime();
 var dur = end - start;
}

但是,Date 对象只有毫秒分辨率,并且会受到操作系统时钟更改的影响。 在现代浏览器中,有一个更好的选项。

更好的选项是使用高分辨率时间,又名 window.performance.now()now() 在两个重要方面优于传统 Date.getTime():

  1. now() 是一个具有亚像素分辨率的double,表示自页面导航开始之后的毫秒数。 它返回分数的微秒数( 例如。 值为 1000.123的值为 1秒和 123微秒) 。

  2. now() 是单调递增的。这是重要 Date.getTime() 可能跳向前或者向后的后续调用。 值得注意的是,如果操作系统时间被更新( 例如。 原子时钟同步),Date.getTime() 也被更新。 now() 保证总是单调递增,所以它不受操作系统时间--的影响它总是wall-clock时间( 假定挂钟不是原子的。。) 。

now() 几乎可以用于 new Date().getTime()+ new Date andt Date.now() 。 例外是 Datenow() 时间不混合,因为 Date 基于 unix-epoch ( 自 1970之后的毫秒数),而 now() 是自页面导航启动之后的毫秒数。

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


function a() {
 var start = window.performance.now();
. . . do stuff.. .
 var end = window.performance.now();
 var dur = end - start;
}

now() 在 Chrome 稳定,Firefox 15 + 和IE10支持。 还有几个 polyfills web 可用。

在野外测量执行时间的另一个选择是 UserTiming 。 UserTiming的行为类似于 console.time()console.timeEnd(),但它使用了 now() 使用( 所以你得到一个sub-millisecond单调的时钟)的相同高分辨率时间戳,并将时间戳和持续时间保存到 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];

UserTiming在IE10+和Chrome25+中可用。 还有一个 polyfill web 可用的( 这是我写的) 。

使用 Firebug,同时启用控制台和 Javascript 。 单击配置文件。重新加载。再次单击配置文件。 查看报表。


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() 是可选的- 只需将false传递到StopWatch构造函数函数。

进一步扩展代码vsync有能力回报timeEnd作为价值NodeJS使用这一小段代码。


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,上网页,等等。

Date.getTime() 或者 console.time() 不适用于精确执行时间。 如果快速粗略估计对你来说可以,你可以使用它们。 粗略估计,我的意思是你可以从实时的时间中得到 15毫秒。

要获得精确的值,应该使用性能接口 。 它支持现代版本的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.")

检查这个出色的post 在JavaScript中测量执行时间。 作者还提供了一些关于JavaScript时间准确性的链接,值得阅读。

process.hrtime() 可在 Node.js ——它返回一个值在纳秒

var hrTime = process.hrtime() 控制台。日志( hrTime [0] * 1000000 + hrTime [1]/1000 )

由于 console.timeperformance.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);
 }
 }
}

...