2、性能分析工具(上):Chrome DevTools Performance 面板详解——录制、分析帧、定位长任务(Long Task)

做性能优化,最怕的就是「凭感觉」。你觉得页面卡,但卡在哪?是 JS 执行太久,还是渲染被阻塞?

我见过太多同学,一上来就改代码,改完发现没效果。其实,第一步应该是用工具说话。

Chrome DevTools 的 Performance 面板,就是我们手里最趁手的「照妖镜」。它能告诉你每一帧发生了什么,哪个函数在拖后腿。

2.1 录制与基础操作

先别急着点那个圆点。录制之前,有几个准备工作要做。

2.1.1 录制前的环境准备

  • 使用无痕窗口:避免浏览器插件干扰。我遇到过某款广告拦截插件,每次录制都会多出几百毫秒的解析时间,排查了半天才发现。
  • 关闭后台应用:尤其是视频、下载任务,它们会抢 CPU 时间片。
  • 固定 CPU 降速:在 Performance 面板的「设置」里,把 CPU 降速调到 4x 或 6x。为什么?因为你的开发机太强了,用户手里的千元机跑起来可能是另一回事。
我的习惯:录制前先清空一下 Console,避免控制台日志干扰。另外,我会先手动操作一遍目标流程,确保没有意外弹窗打断录制。

2.1.2 开始录制与停止

点击面板左上角的灰色圆点(或按 Ctrl+E),开始录制。此时页面上的所有操作都会被记录下来。

操作完成后,点击红色的「Stop」按钮。你会看到一张密密麻麻的时间线图表——别慌,我们一步步拆解。

注意:录制时间不要超过 10 秒。时间越长,数据量越大,分析起来反而困难。我一般只录制 3-5 秒的关键操作。

2.2 读懂火焰图与帧分析

录制完成后,你会看到三个主要区域:顶部的概览、中间的火焰图、底部的详情面板。

2.2.1 概览区域

概览区域有三条折线:CPU、NET、HEAP。

  • CPU:如果这条线长时间处于高位(接近 100%),说明你的 JS 执行或渲染任务太重了。
  • NET:网络请求的耗时。如果这里出现长条,说明资源加载是瓶颈。
  • HEAP:内存使用量。如果曲线持续上升不回落,可能有内存泄漏。

2.2.2 火焰图(Main Thread)

这是整个面板的核心。每一行代表一个调用栈,宽度代表耗时。

看火焰图有个技巧:从下往上看。底部的「Task」是根任务,越往上越是具体的函数调用。

如果某个「Task」的宽度超过 50ms,它就是一个 长任务(Long Task)。为什么是 50ms?因为浏览器需要保证 60fps 的渲染,每一帧只有约 16.67ms。一个任务超过 50ms,意味着它至少阻塞了 3 帧。

关键指标:

  • 绿色条:渲染(Paint / Composite)
  • 黄色条:JS 执行(Scripting)
  • 紫色条:样式计算(Style / Layout)
  • 灰色条:空闲(Idle)

如果黄色或紫色条特别宽,那就是优化的重点区域。

2.2.3 帧分析(Frames)

在火焰图上方,有一行灰色的竖线,每一根代表一帧。如果某一帧的竖线变成了红色,说明这一帧的耗时超过了 16.67ms,用户会感觉到卡顿。

点击红色的帧,底部详情面板会显示这一帧的具体耗时分布:

阶段 正常耗时 警告阈值
Scripting < 5ms > 10ms
Style / Layout < 3ms > 8ms
Paint < 2ms > 5ms
Composite < 1ms > 3ms

我曾经优化过一个列表页,每次滚动都会触发大量的 Style 计算。一看帧分析,Style 阶段占了 12ms。后来发现是 CSS 选择器写得太复杂,改完后降到了 2ms。

2.3 定位长任务(Long Task)

长任务是卡顿的元凶。怎么快速找到它?

2.3.1 使用「Long Tasks」标记

在火焰图里,长任务会用红色的锯齿状边框标记出来。你还可以在「Summary」面板里勾选「Long Tasks」,它会高亮所有超过 50ms 的任务。

2.3.2 分析调用栈

点击一个长任务,底部会显示它的调用栈。比如:

Task (55.2ms)
  ├── Function Call (48.1ms)
  │   ├── handleClick (30.2ms)
  │   │   └── updateList (28.5ms)
  │   │       └── renderItems (25.1ms)
  │   └── requestAnimationFrame (17.9ms)
  └── Layout (7.1ms)

看到 renderItems 占了 25.1ms,这就是我们要优化的目标。

2.3.3 避坑指南

我曾经遇到一个情况:火焰图里显示一个长任务只有 30ms,但页面依然卡顿。后来发现,这个任务虽然短,但它触发了强制同步布局(Forced Reflow)。

怎么发现?在详情面板里搜索「Layout」或「Recalculate Style」,如果它们出现在 JS 执行阶段中间,而不是在渲染阶段,那就是强制同步布局。

快速定位技巧:在火焰图上按住鼠标左键拖动,可以框选一段区域。然后按 W 键放大,按 S 键缩小。我习惯先框选一个红色帧,然后放大看细节。

2.4 知识体系图

下面这张图总结了 Performance 面板的核心分析流程:

Performance 面板分析流程 1. 录制操作 2. 概览:CPU / NET / HEAP 3. 火焰图:识别长任务(>50ms) 帧分析:检查红色帧 调用栈:定位耗时函数 4. 输出优化方案 长任务 → 拆分 / 异步

2.5 实战:一次完整的分析过程

假设你发现页面点击按钮后,有 200ms 的延迟。我们来走一遍流程:

  1. 录制:打开无痕窗口,CPU 降速 4x,点击按钮,停止录制。
  2. 看概览:CPU 曲线在点击后瞬间飙到 100%,持续了约 200ms。
  3. 找长任务:火焰图里有一个红色的长任务,宽度约 180ms。
  4. 分析调用栈:点击长任务,看到 handleClick 内部调用了 processData,耗时 150ms。
  5. 检查帧:点击附近的红色帧,发现 Layout 阶段耗时 12ms,说明有强制同步布局。

优化方向就很明确了:把 processData 拆成多个小任务,用 requestAnimationFrame 或 setTimeout 分批执行;同时修复强制同步布局的问题。

曾经踩过的坑:有一次我优化了一个长任务,从 80ms 降到了 20ms,但页面还是卡。后来发现是另一个隐藏的定时器在持续触发重排。所以,分析时不要只看最大的那个长任务,也要留意那些频繁出现的小任务。

Performance 面板就像医生的听诊器。你用得越熟练,诊断速度就越快。刚开始可能会觉得信息太多,但只要你坚持用几次,慢慢就能一眼看出问题所在。