如何操作性能优化_JavaScript中代码性能如何监控和提升

console.time() 用于快速测量代码段执行耗时,需与同名 console.timeEnd() 成对使用;performance.mark()/measure() 更适合跨函数、异步的端到端性能分析。

怎么用 console.time() 快速定位慢函数

直接测某段代码执行耗时,比猜快得多。它不依赖外部工具,适合开发阶段快速验证。

  • console.time()console.timeEnd() 必须成对出现,且传入的标签名(字符串)要完全一致,否则 timeEnd() 会报 Timer “xxx” doesn’t exist
  • 不要在循环里反复调用同一名字的 console.time(),Chrome 会覆盖上一次计时器,导致结果不准
  • 它只统计 JS 主线程执行时间,不包含渲染、GC 或异步回调延迟,适合测纯逻辑瓶颈
console.time('parseData');
const result = JSON.parse(largeJsonString);
console.timeEnd('parseData'); // 输出:parseData: 124.345ms

为什么 performance.mark() + performance.measure() 更适合复杂流程

当你要跨函数、跨异步阶段(比如从点击到渲染完成)测端到端耗时,console.time() 就力不从心了。

  • performance.mark() 打点无开销,可打多个;performance.measure() 按标记名计算差值,支持异步场景
  • 必须先 mark()measure(),否则返回 NaN;标记名区分大小写
  • 配合 performance.getEntriesByType('measure') 可导出结构化数据,方便自动化分析
performance.mark('start-fetch');
fetch('/api/data').then(() => {
  performance.mark('end-fetch');
  performance.measure('fetch-duration', 'start-fetch', 'end-fetch');
});

哪些操作会意外触发强制同步布局(Layout Thrashing)

这是前端性能隐形杀手——每次读取布局属性(如 offsetHeight)后立刻写样式,浏览器被迫同步重排,严重拖慢帧率。

  • 常见组合:el.offsetHeightel.style.height = '200px' → 再读 el.scrollHeight
  • DOM 查询(getBoundingClientRect(), computedStyle)也触发重排,别在循环里反复调用
  • requestAnimationFrame() 批量读写:所有读操作放一帧开头,所有写操作放同一帧末尾

chrome://tracing 抓真实用户卡顿帧,比 DevTools 面板更准

DevTools 的 Performance 面板默认只录主线程,而 chrome://tracing 能同时捕获 GPU、Raster、V8、IO 等多线程事件,暴露真正瓶颈。

  • 启动前勾选 disabled-by-default-v8.runtime_stats,才能看到 JS 函数级耗时(否则只有“Evaluate Script”大块)
  • 录制时避免开太多标签页,否则系统调度干扰数据;建议用隐身窗口+禁用所有扩展
  • 重点关注 Long Tasks(>50ms)和 Recalculate Style / Layout 高频区间,它们常对应可优化的代码段

实际优化中,最易被忽略的是微任务队列堆积——比如连续 20 次 Promise.resolve().then(...),会阻塞后续渲染帧。这类问题只能靠 tracing 抓到,console.time() 完全测不出来。