performance.mark() 不能直接用重复字符串名打点,因为同名标记会覆盖而非追加;应使用语义化+时间戳/随机后缀的唯一命名,如'cart-submit-begin';performance.measure()需显式传入起止mark名,任一缺失则静默失败;建议用traceId透传、try/finally确保end标记执行,并在关键路径结束后用clearMarks()按前缀清理,避免内存泄漏。
因为 performance.mark() 要求标记名是合法的 DOMString,但更关键的是:**重复调用同一名字会覆盖前一次记录**,不是追加。如果你在用户点击按钮、请求发出、数据渲染三个阶段都写 performance.mark('load'),最后只能拿到最后一次的时间戳,中间过程全丢了。
实操建议:
'click-start-1744631354823' 或 'api-fetch-init-uuid4'
'cart-submit-begin'、'cart-submit-api-resolved'、'cart-submit-dom-updated'
@、/),否则后续 performance.measure() 可能抛 SyntaxError
performance.measure() 不是自动计算差值,它依赖你显式传入起止 mark 名 —— 如果其中任一 mark 未被记录,measure 就不会生成条目,也不会报错,容易静默失效。
常见错误现象:
performance.measure('api-latency', 'api-start', 'api-end'),但 'api-end' 标记因异常没执行,结果 performance.getEntriesByType('measure') 查不到该条目'Api-Start' 却用 'api-start' 去 measure'api-end')安全做法:
const traceId = Date.now().toString(36) + Math.random().toString(36).substr(2, 5)
try/finally 包裹异步逻辑,确保 end mark 必然执行const m = performance.getEntriesByName('api-latency'); if (!m.length) console.warn('Missing measure: api-latency');
浏览器不会自动聚合或格式化 performance.getEntriesByType('measure') 的结果。你拿到的是原始 PerformanceMeasure 对象数组,duration 字段单位是毫秒,但精度为微秒级(小数点后三位),直接 console.log() 显示不够直观。
输出建议:
performance.getEntriesByType('measure').filter(m => /^cart-.*/.test(m.name))
startTime 排序,还原执行时序;用 Math.round(m.duration * 100) / 100 保留两位小数const report = measures.map(m => ({ name: m.name, duration: Math.round(m.duration * 100) / 100, startTime: m.startTime.toFixed(1), entryType: m.entryType}));
注意:performance.getEntriesByType('measure') 返回的是快照,不会包含之后新增的 measure,所以应在关键路径全部结束(如页面加载完成、用户操作流收尾)后再调用。
会。所有通过 performance.mark() 和 performance.measure() 创建的条目都会保留在 PerformanceEntryBuffer 中,除非主动清理或页面卸载。在单页应用中反复进入同一页面、打大量临时 mark,可能让 buffer 持续增长,尤其在低内存设备上影响明显。
必须做的清理动作:
performance.clearMarks(traceIdPrefix) 清除本次路径相关 mark(支持传入字符串前缀)performance.clearMeasures('cart-submit-latency') 或批量清空:performance.clearMeasures()
最容易被忽略的一点:**mark 名设计必须可预测、可批量清理**。如果用随机 UUID 打点却不保存,就无法精准清除,最后只能用 performance.clearMarks() 全局清空,连带删掉其他模块的监控数据。