幽灵与熔断漏洞出现后,如何在JavaScript中实现微秒级代码计时?
解决JavaScript细粒度性能分析的痛点
我太懂这种在Chrome等浏览器里用自带性能工具分析高性能JS代码的憋屈了!那些工具大多只能到函数级粒度,真要定位到某几行代码的性能瓶颈,得耗大把时间翻数据,效率低得离谱。
用过.NET的朋友肯定知道StopWatch有多香——随便选一段代码就能做亚微秒级的精准计时,想测哪段测哪段,粒度细得很,完全能满足精准排查性能问题的需求。
之前大家常用performance.now()来做JS性能测量,确实比Date.now()精度高不少,但它有个头疼的问题:没办法方便地做嵌套计时、分组统计,而且每次都要手动记录开始和结束时间,代码写起来又臭又长。如果要测多个代码段,或者嵌套的逻辑,光是维护那些时间戳变量都能把人搞疯。
其实我们可以自己封装一个类似StopWatch的工具类,用performance.now()做底层,实现便捷的细粒度计时。比如这样:
class StopWatch { constructor() { this.startTime = null; this.elapsedTime = 0; this.isRunning = false; } start() { if (!this.isRunning) { this.startTime = performance.now(); this.isRunning = true; } } stop() { if (this.isRunning) { const endTime = performance.now(); this.elapsedTime += endTime - this.startTime; this.isRunning = false; } } reset() { this.startTime = null; this.elapsedTime = 0; this.isRunning = false; } get elapsedMilliseconds() { if (this.isRunning) { const currentTime = performance.now(); return this.elapsedTime + (currentTime - this.startTime); } return this.elapsedTime; } }
用起来就跟.NET的StopWatch一样顺手:
const watch = new StopWatch(); // 测一段同步代码 watch.start(); // 你的目标代码段:比如复杂的数组处理、DOM操作 for (let i = 0; i < 100000; i++) { Math.sqrt(i); } watch.stop(); console.log(`同步代码耗时:${watch.elapsedMilliseconds.toFixed(3)}ms`); // 重置后测嵌套逻辑 watch.reset(); watch.start(); fetch('/api/data') .then(res => res.json()) .then(data => { watch.stop(); console.log(`API请求耗时:${watch.elapsedMilliseconds.toFixed(3)}ms`); // 再测数据处理 watch.start(); processData(data); watch.stop(); console.log(`数据处理耗时:${watch.elapsedMilliseconds.toFixed(3)}ms`); });
如果需要更复杂的分组统计,比如同时测多个并行的代码段,还可以扩展这个类,加入lap()方法记录分段时间,或者用Map来管理多个计时器实例,方便对比不同代码路径的性能。
内容的提问来源于stack exchange,提问作者Fred Kleuver
相关产品推荐
相关产品推荐

