如何测量函数的执行时间

如何测量函数的执行时间

技术背景

在开发过程中,测量函数的执行时间对于性能优化至关重要。通过了解函数的执行时间,我们可以找出性能瓶颈,优化代码,提高应用程序的响应速度和效率。JavaScript 提供了多种方法来测量函数的执行时间,下面将详细介绍这些方法。

实现步骤

1. 使用 performance.now()

performance.now() 方法返回一个表示当前时间的高精度时间戳,其精度可以达到微秒级别。在 Node.js 中,需要导入 performance 类。

1
2
3
4
5
6
7
// 在 Node.js 中导入 performance 类
const { performance } = require('perf_hooks');

const startTime = performance.now();
doSomething(); // 要测量的代码
const endTime = performance.now();
console.log(`Call to doSomething took ${endTime - startTime} milliseconds`);

2. 使用 console.time()console.timeEnd()

console.time() 用于启动一个计时器,console.timeEnd() 用于停止计时器并输出执行时间。传入的字符串必须匹配。

1
2
3
console.time('doSomething');
doSomething(); // 要测量的函数
console.timeEnd('doSomething');

3. 使用 new Date().getTime()

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

1
2
3
4
5
6
7
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);

4. 使用 UserTiming

UserTiming 类似于 console.time()console.timeEnd(),但它利用了与 performance.now() 相同的高分辨率时间戳,并将时间戳和持续时间保存到 PerformanceTimeline 中。

1
2
3
4
5
6
7
function a() {
window.performance.mark("start");
// do stuff
window.performance.measure("myfunctionduration", "start");
// 获取持续时间
var duration = window.performance.getEntriesByName("myfunctionduration", "measure")[0];
}

核心代码

装饰器实现函数计时

1
2
3
4
5
6
7
8
9
10
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;
}

let test = () => { /* does something */ }
test = timed(test);
test();

自定义计时器类

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

最佳实践

  • 优先使用 performance.now()performance.now() 提供了更高的精度和更稳定的时间测量,不受系统时间变化的影响。
  • 使用浏览器的性能分析工具:现代浏览器都内置了 JavaScript 性能分析工具,如 Chrome 的开发者工具中的 Profiles 标签,可以提供更详细的性能分析。
  • 避免使用 Date 对象进行时间测量Date 对象的精度较低,并且会受到系统时间变化的影响,可能会导致测量结果不准确。

常见问题

1. Date 对象测量时间不准确

由于 Date 对象的精度较低,并且会受到系统时间变化的影响,因此不适合用于精确的时间测量。建议使用 performance.now()UserTiming

2. console.time()console.timeEnd() 的字符串不匹配

console.time()console.timeEnd() 传入的字符串必须匹配,否则计时器将无法正常停止。

3. 异步函数的时间测量

对于异步函数,需要在异步操作完成后再记录结束时间,否则测量结果将不准确。可以使用回调函数、Promise 或 async/await 来确保在异步操作完成后记录结束时间。


如何测量函数的执行时间
https://119291.xyz/posts/how-to-measure-time-taken-by-a-function-to-execute/
作者
ww
发布于
2025年5月26日
许可协议