Performance 面板是 DevTools 中最强大的性能分析工具。它不仅能告诉你"页面卡不卡",还能精确告诉你"卡在哪里"、"为什么卡"、"怎么优化"。
浏览器渲染一个帧的完整流程:
关键事实:在 60fps 的目标下,每一帧的预算只有 16.67ms(1000ms / 60)。如果某个环节耗时超过这个预算,就会导致掉帧,用户感知到卡顿。
理想帧预算拆解(Main 线程一帧的可分配时间):
理想帧:JS(3ms) + Style(1ms) + Layout(2ms) + Paint(3ms) + Composite(1ms) = 10ms ✅
问题帧:JS(15ms) + Layout(5ms) + Paint(3ms) = 23ms ❌(超出 16.67ms 预算)常见瓶颈模式:
| 模式 | 火焰图特征 | 原因 | 解决方案 |
|---|---|---|---|
| 长任务 | 黄色块 > 50ms | 复杂计算 | 拆分任务 / Web Worker |
| 布局抖动 | 交替的紫-黄-紫 | 读写布局属性交替 | 批量读写分离 |
| 强制同步布局 | JS 中嵌套紫色布局 | offsetHeight 等触发布局 | 缓存布局值 |
| 频繁 GC | 灰色 GC 块 | 短命对象过多 | 对象池 / 减少分配 |
| 指标 | 衡量什么 | 良好 | 需要改进 | 差 |
|---|---|---|---|---|
| LCP (Largest Contentful Paint) | 加载性能 | ≤ 2.5s | ≤ 4.0s | > 4.0s |
| INP (Interaction to Next Paint) | 交互响应 | ≤ 200ms | ≤ 500ms | > 500ms |
| CLS (Cumulative Layout Shift) | 视觉稳定性 | ≤ 0.1 | ≤ 0.25 | > 0.25 |
🆕 INP 在 2024 年 3 月正式取代 FID (First Input Delay) 成为 Core Web Vitals 指标。INP 衡量的是整个页面生命周期中最慢的交互延迟,而非仅首次输入。
2024-2026 更新:Chrome DevTools Performance 面板进行了重大 UI 改版,新增了多个轨道和功能。
关键轨道说明:
| 轨道 | 说明 |
|---|---|
| FPS | 每秒帧数,低于 60fps 时变红 |
| CPU | CPU 使用率 |
| NET | 网络请求时间线 |
| Screenshots | 每帧的截图 |
| Interactions | 用户交互事件(click、keydown 等),新增 |
| Main | 主线程任务火焰图(最核心的轨道) |
| Network | 网络请求详情 |
| Timings | LCP、FCP、User Timing 标记 |
4x slowdown 或 6x slowdown(模拟低端设备)Fast 3G 或 Slow 3G| 方式 | 操作 | 适用场景 |
|---|---|---|
| 普通录制 | 点击 Record → 操作页面 → Stop | 分析特定交互的性能 |
| 重载录制 | 点击 🔄 "Start profiling and reload page" | 分析页面加载性能 |
| Recorder 集成 | 在 Recorder 面板录制用户流程 | 可复现的性能分析 |
不同颜色代表不同类型的活动:
| 颜色 | 活动类型 | 含义 |
|---|---|---|
| 🟡 黄色 | Scripting | JavaScript 执行 |
| 🟣 紫色 | Rendering | 样式计算 + 布局 |
| 🟢 绿色 | Painting | 绘制 + 光栅化 |
| ⚪ 灰色 | System | 浏览器内部工作 |
| 🔵 蓝色 | Idle | 空闲 |
火焰图是 Performance 面板的核心。它展示了主线程上每个任务的调用栈:
阅读火焰图的技巧:
选中火焰图中的任意任务,Summary 显示该任务的时间分布饼图:
| 类别 | 说明 |
|---|---|
| Loading | 网络请求、HTML 解析 |
| Scripting | JS 执行、事件处理、定时器 |
| Rendering | 样式计算、布局 |
| Painting | 绘制、图层化、光栅化 |
| System | 浏览器内部任务 |
| Idle | 空闲时间 |
Performance Insights 是 Chrome 102+ 引入的智能分析面板,旨在降低性能分析的门槛。
| 维度 | Performance 面板 | Performance Insights |
|---|---|---|
| 定位 | 专家级原始数据 | 智能分析与建议 |
| 输出 | 火焰图 + 原始时间线 | 洞察卡片 + 优化建议 |
| 门槛 | 需要理解浏览器渲染原理 | 面向所有开发者 |
| 适用 | 深度性能调优 | 快速性能诊断 |
preload/fetchpriority交互延迟(INP)可以在 Interactions 轨道中精准定位:
2024-2026 新增:Chrome 123+ 支持 Long Animation Frames API,比 Long Tasks API 更精确地检测长任务。它不仅检测单个长任务,还检测整个动画帧(包括样式计算、布局、绘制)是否超时。
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log('Long animation frame:', {
duration: entry.duration,
startTime: entry.startTime,
scripts: entry.scripts.map(s => ({
name: s.name,
duration: s.duration,
type: s.type, // classic / module / event-handler etc.
invoker: s.invoker, // 触发者
})),
});
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });对比:
现象:在火焰图中看到交替出现的紫色(Layout)和黄色(Scripting)块。
原因:JavaScript 在修改 DOM 后立即读取布局属性,触发了强制同步布局:
// ❌ 强制同步布局
elements.forEach(el => {
el.style.width = '100px' // 写
const height = el.offsetHeight // 读 → 触发 Layout
el.style.height = height + 'px' // 写
})
// ✅ 批量读写分离
elements.forEach(el => {
el.style.width = '100px' // 批量写
})
elements.forEach(el => {
const height = el.offsetHeight // 批量读
el.style.height = height + 'px' // 批量写
})当强制同步布局在循环中发生时,就变成了布局抖动——每轮迭代都触发一次 Layout,性能呈指数级下降。
在火焰图中识别:多个连续的紫色 Layout 块,每个之间夹着很短的黄色 Scripting 块。
识别:火焰图中带红色三角标记的块(> 50ms)。
常见原因:
优化策略:
requestAnimationFrame 将任务分散到多个帧setTimeout(fn, 0) 或 scheduler.postTask() 分片内存泄漏的典型火焰图特征:GC(垃圾回收)事件越来越频繁,每次 GC 耗时越来越长。详见第 7 章 Memory。
通过 Command Menu (Cmd + Shift + P) → Show Rendering 打开渲染调试工具:
| 选项 | 作用 |
|---|---|
| Paint flashing | 绿色高亮显示正在被重绘的区域 |
| Layout Shift Regions | 蓝色高亮显示布局偏移区域 |
| Layer borders | 显示合成层边界(橙色边框 = 独立合成层) |
| FPS meter | 实时帧率显示 |
| Scrolling performance issues | 高亮可能影响滚动性能的元素 |
Paint flashing 实战:
优化方向:
will-change 或 transform: translateZ(0) 将频繁变化的元素提升为独立合成层top/left/width/height,改用 transform 和 opacity减少布局触发:
DocumentFragment 或 display: none 包裹)requestAnimationFrame 将布局操作安排在帧开始时