首选performance.now(),因其返回从navigationstart起的微秒级浮点毫秒值,单调递增、不受系统时钟干扰、开销极低;而定时器是调度工具非计时器,date.now()仅毫秒精度且易受系统时间跳变影响。

评估代码执行耗时,核心是选对时间源:优先用 performance.now(),不用定时器(如 setTimeout、setInterval)或 Date.now() 来测真实运行时间。
为什么 performance.now() 是首选
它返回的是从页面加载开始的高精度浮点毫秒值(比如 12345.6789),精度通常达微秒级,且完全不受系统时钟跳变、夏令时、手动调时间等干扰。关键特性包括:
- 单调递增:数值永远不会倒退,适合做差计算
- 相对起点稳定:以
navigationStart为零点,不依赖系统时间 - 开销极低:V8 和 Blink 已深度优化,单次调用几乎无性能损耗
定时器不能用来“测耗时”的原因
定时器(setTimeout、setInterval)本质是调度机制,不是计时工具。它们的触发时间受事件循环、任务队列、主线程阻塞等因素影响,和代码实际执行时间无关。
- 例如:
setTimeout(() => console.log('done'), 0)并不表示“立刻执行”,而是“尽快在下一个宏任务执行” - 若主线程正忙于长任务,定时器回调可能延迟几十甚至上百毫秒,完全无法反映被测代码的真实耗时
- 把定时器当作“打点工具”会混淆调度延迟与执行耗时,导致误判瓶颈
和 Date.now() 的关键区别
Date.now() 返回整数毫秒值,易受系统时间修改影响——用户调快/调慢系统时间,会导致测出负值或大幅偏差;而 performance.now() 不会。
- 精度差异:Date.now() 最小单位是 1ms;performance.now() 可达 0.001ms(1μs)
- 适用场景不同:Date.now() 适合记录日志时间戳、计算日期间隔;performance.now() 专为性能测量设计
- 异步场景中尤其明显:比如 fetch 后用 Date.now() 算总延迟,若期间系统时间被改,结果就不可信
正确使用 performance.now() 的实操要点
不是调两次就行,关键在位置和上下文:
- 起始点必须紧贴待测代码前一行,结束点紧贴后一行,中间不插入
console.log等可观测操作(DevTools 开着时它本身有开销) - 同步代码直接套用:start → 执行 → end → 相减
- 异步逻辑要分段打点:比如
await api()前后各一次,或在.then()里再取一次,避免混入网络等待时间 - 需要长期追踪或可视化时,配合
performance.mark()和performance.measure(),才能在 DevTools Performance 面板里看到标记轨迹











