推荐用 performance.now() 做轻量单次测量,或用 performance.mark() + performance.measure() 做结构化耗时追踪;两者精度高、不受系统时间跳变影响,且原生支持。

在 JS 项目中测量关键代码耗时,推荐用 performance.now() 做轻量单次测量,或用 performance.mark() + performance.measure() 做结构化、可归档的耗时追踪。两者都比 Date.now() 更准,不受系统时间跳变影响,且原生支持,无需引入额外依赖。
用 performance.now() 快速测一段逻辑
适合调试验证、CI 中的性能断言,或监控简单函数执行时间:
- 调用
performance.now()获取起始高精度时间戳(单位毫秒,精度可达微秒级) - 执行目标代码(同步逻辑)
- 再次调用
performance.now(),相减即得真实耗时
示例:
function processData(data) { return data.map(x => x * 2); }const start = performance.now();
processData([1, 2, 3, 4]);
const end = performance.now();
console.log(`processData 耗时: ${(end - start).toFixed(2)} ms`);
用 mark 和 measure 追踪多阶段流程
适合组件生命周期、接口请求链路、首屏渲染路径等需长期分析和上报的场景,结果可在 Chrome DevTools 的 Performance 面板中可视化:
- 在关键节点调用
performance.mark('xxx-start')和performance.mark('xxx-end'),命名要有语义(如'fetch-user-start') - 用
performance.measure('xxx-duration', 'xxx-start', 'xxx-end')创建测量条目 - 标记名必须唯一;重复调用同名
mark会报错(DOMException),异步场景建议拼接时间戳或使用唯一 ID
示例:
performance.mark('api-login-start');fetch('/login').then(() => {
performance.mark('api-login-end');
performance.measure('login-api-duration', 'api-login-start', 'api-login-end');
});
提取并上报测量数据
measure 不自动上报,需主动获取、过滤后发送到监控服务:
- 按类型提取:
performance.getEntriesByType('measure')拿全部测量项 - 按名称精确提取:
performance.getEntriesByName('login-api-duration', 'measure') - 每条 entry 包含
name、startTime、duration(核心字段)、entryType - 建议过滤掉
duration ≤ 0的异常记录,再通过fetch或new Image().src打点上报
示例上报逻辑:
const entries = performance.getEntriesByName('login-api-duration', 'measure');if (entries.length && entries[0].duration > 0) {
sendToMonitor({
type: 'api-login',
duration: Math.round(entries[0].duration),
path: window.location.pathname,
timestamp: Date.now()
});
}
注意清理与兼容性
避免内存堆积和跨环境问题:
- 长期运行的应用(如 SPA)建议在路由切换或空闲时段调用
performance.clearMarks()和performance.clearMeasures() - 异步操作必须在回调或
await后打结束 mark,否则测的是调度延迟而非真实执行 - 兼容性良好:Chrome 25+、Firefox 41+、Edge 12+、Safari 11+,无需 polyfill
- 不要用已废弃的
performance.timing,改用performance.getEntriesByType('navigation')[0]获取导航数据


















