核心是分层打点、唯一命名、对齐渲染、严格验证:按准备/触发/响应/渲染/可见阶段语义化命名;用traceId确保mark名唯一;配合rAF锚定真实渲染节点;上线前用getEntriesByName校验落点,measure前检查起止mark存在性。

在 JS 项目中用 performance.mark 标记复杂流程,核心是让每个标记真实反映业务阶段、可归因、可测量、不被覆盖。不能只打点,得有结构、有上下文、有验证。
按业务阶段分层打点,不拼凑也不复用
一个完整流程(比如“商品搜索→请求→渲染→可见”)应拆解为语义明确的原子阶段,每个阶段一个独立 mark 名:
-
准备阶段:如
'search-input-debounce-end'(防抖结束,准备发请求) -
触发阶段:如
'search-api-request-start'(fetch 调用前一刻) -
响应阶段:如
'search-api-response-parsed'(JSON 解析完成,数据可用) -
渲染阶段:如
'search-results-dom-mounted'(真实 DOM 插入完成) -
可见阶段:如
'search-results-in-viewport'(首项进入视口,用户真正看到)
同一链路里禁止复用名字(如全叫 'search-done'),否则 measure 会取错起点或直接失效。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
确保 mark 名唯一且可统计
重复名会被覆盖,动态 ID 是刚需:
- 用 traceId 统一透传,例如:
const traceId = Date.now().toString(36) + Math.random().toString(36).substr(2, 5) - 构造 mark 名时带上 traceId:
`search-api-request-start-${traceId}` - 禁用拼接业务 ID(如
`item-${id}`),否则无法做 p95/p99 或趋势分析 - 统一小写 + 短横线格式,避免空格、斜杠、@ 等非法字符
配合生命周期钩子对齐真实耗时节点
mark 本身不绑定渲染时机,需与浏览器执行节奏对齐:
- DOM 更新确认点:在
requestAnimationFrame回调中打'raf-dom-updated' - 视觉呈现确认点:嵌套第二层 rAF,打
'raf-painted'(最接近“上帧”的信号) - 避免在
setTimeout(0)或queueMicrotask中打点——它们只保证 JS 执行顺序,不保证 layout/paint 完成 - React/Vue 场景下,
useEffect或nextTick后仍需再等 rAF,才能代表真实渲染就绪
上线前必须验证 mark 是否真实落库
打点失败不会报错,但数据就丢了:
- 上线前加校验:
performance.getEntriesByName('search-api-request-start', 'mark').length—— 返回 0 就说明没打进 PerformanceEntry - measure 前先检查起止 mark 是否都存在:
if (!performance.getEntriesByName('start').length || !performance.getEntriesByName('end').length) console.warn('Missing mark') - 关键路径建议用
try/finally包裹,确保 end mark 必然执行(尤其异步出错时) - 批量清理避免内存泄漏:
performance.clearMarks({ type: 'mark', name: /^search-/ })

















