最轻量原生高精度自定义性能埋点方式是:用performance.mark()打语义化标记(如'user-login-start',名须唯一不重复),再用performance.measure()计算两点间毫秒耗时并存入timeline,最后通过getEntriesByName或getEntriesByType手动提取duration等字段并上报。

直接用 performance.mark() 打点,再用 performance.measure() 算耗时,最后通过 getEntriesByType 或 getEntriesByName 提取数据——这是最轻量、原生、高精度的自定义性能埋点方式。
怎么打语义化标记(mark)
在关键逻辑节点插入 performance.mark(name),名字必须是字符串,且不能重复(重复会抛 DOMException 错误)。
- 命名要有业务含义,比如
'user-login-start'、'list-render-complete' - 适合标记函数入口/出口、异步开始/结束、渲染完成、模块加载完成等节点
- 如需覆盖旧标记,先调
performance.clearMarks('name')
怎么计算两点之间耗时(measure)
调用 performance.measure(name, startMark, endMark),它会自动计算两个 mark 之间的毫秒差,并存入 performance timeline。
-
startMark和endMark必须已存在,且endMark要在startMark之后执行(异步场景注意顺序) - 例如:
performance.measure('login-total', 'user-login-start', 'user-login-end') - 生成的记录类型为
'measure',可通过getEntriesByType('measure')批量获取
怎么取数并上报
measure 不自动上报,需手动提取、过滤、发送。
- 推荐按名精确取:
performance.getEntriesByName('login-total', 'measure') - 每条 entry 包含
name、duration(核心耗时)、startTime等字段 - 建议过滤掉
duration ≤ 0的异常项,再用fetch或new Image().src上报 - 开发环境可加守卫:
if (location.hostname === 'localhost') { ... }
怎么避免常见坑
几个容易忽略但影响结果准确性的细节:
- 不要在循环体或高频回调里无条件打 mark,容易触发内存警告或命名冲突
- 避免在断点暂停后手动执行 mark —— 断点会拉长真实耗时,应让代码连续运行
- 长时间运行的页面记得定期清理:
performance.clearMarks()、performance.clearMeasures() - Chrome 外浏览器不支持
performance.memory,但 mark/measure 全平台兼容(Chrome 25+、Firefox 41+、Edge 12+、Safari 11+)



















