原作者:Kayce Basques。本文依据 Chrome for Developers 的 Analyze runtime performance 全文翻译整理。原页最后更新于 2024-10-23,教程明确基于 Chrome 129;本次全文核对日期为 2026-10-05。
运行期性能描述页面已经运行起来之后的表现,与首次加载速度不同。在 RAIL 模型里,下面的技能主要用于检查 Response(响应)、Animation(动画)与 Idle(空闲)阶段。我们将沿着一次性能录制,从帧表现、CPU 活动和主线程调用栈中找到动画卡顿的原因,再用同样条件下的新录制判断改动是否减少了工作。

一、建立容易比较的演示环境
用 Chrome 无痕窗口打开官方演示:上下移动的蓝色方块。原文采用无痕模式是为了减少浏览器扩展等环境噪声。它不能保证没有任何扩展运行,也不能消除设备温度、后台任务等影响,因此比较时仍要保持环境一致。
macOS 按 Command+Option+I,Windows 或 Linux 按 Control+Shift+I 打开 DevTools。为了容纳更完整的面板,原文后续截图将 DevTools 分离到独立窗口;是否分离不改变分析原理。
用 CPU 降速制造可观察的负载
- 切换到 Performance 面板。
- 启用 Screenshots,让录制保存时间轴对应的页面画面。
- 打开 Capture Settings。
- 把 CPU 设为
4x slowdown。
原文用四倍降速演示性能受限时的表现,并提到在其他页面上可尝试更强的 20x slowdown 检查低端设备情境。但这段方块演示在 20 倍降速下不适合教学,所以采用四倍。降速是在当前计算机上施加限制,不能把结果等同于某一型号手机的真实表现;这是本文补充的测量边界。
调整方块数量
反复点击 Add 10,直到方块明显比一开始移动得慢。原文提示高性能机器可能需要约 20 次点击,这只是环境相关的经验值。点击 Optimize,观察动画是否变得更流畅;然后点击 Un-Optimize,回到有卡顿的状态,为接下来的录制做准备。
如果优化前后没有明显区别,可以点击几次 Subtract 10 后再比较。添加过多方块会让 CPU 在两个版本下都饱和,差异反而被掩盖。教学重点是构造可以比较的负载,而不是不断加重压力。
二、录下尚未优化的动画
两个版本本来都希望在相同时间里移动相同距离,但优化版本看起来更快。要解释这个差异,应记录浏览器具体做了什么,而不只凭肉眼判断。
- 在 Performance 面板点击 Record。
- 让页面运行几秒钟。
- 点击 Stop,等待 DevTools 处理并显示录制结果。
第一次看到这些数据可能会觉得拥挤。先把问题缩小为两个:动画什么时候表现不好?那段时间主线程忙于哪些工作?接下来分别用帧信息和调用栈回答。
三、先判断帧表现,再观察 CPU
原文以每秒帧数 FPS 作为动画表现的主要观察指标,并以 60 FPS 作为教学目标。补充说明:60 FPS 对应大约 16.7 毫秒一个显示间隔,这只是换算,不是本次测量;高刷新率屏幕的预算更紧。还应注意每帧是否按时完成,不能只用平均 FPS 代表所有体验。
在原文界面中,FPS 图上方出现红条,表示该时间段帧率下降到可能影响体验的程度。查看它下方的 CPU 图,颜色与面板底部 Summary 标签页中的活动类别对应。原文演示里 CPU 图长时间几乎被各类活动填满,提示应该寻找减少工作的机会;并不是所有彩色区域都意味着同一种瓶颈。
把鼠标移到 FPS、CPU 或 NET 概览图上,可以看到该时间点的页面截图。左右移动鼠标相当于沿录制回放画面,这种浏览时间轴的方式称为 scrubbing。它适合把“我看到某段动画停顿”与“时间轴上同一位置的工作”联系起来。
在 Frames 轨道中,将鼠标悬停于某一帧的绿色方块,原文版本会显示该帧的 FPS。演示中的多数帧低于作者设定的 60 FPS 目标。在真实页面里,卡顿可能只出现在短暂交互中,这些分帧数据通常比单次肉眼观察更有用。
可选:打开实时帧率显示
按 macOS 的 Command+Shift+P 或 Windows/Linux 的 Control+Shift+P 打开 Command Menu,输入 Rendering,选择 Show Rendering。在 Rendering 面板中启用 Show Rendering stats,视口右上角会出现实时估算信息。
这是原文额外介绍的观察工具。使用后关闭该显示,再按 Escape 收起 Rendering 面板;后面的定位仍以已录制的 Performance 数据为主。不同版本可能将该功能称为 FPS meter 或使用不同标签。
四、从 Summary 缩小到一次动画回调
在没有选择单个事件时,Summary 展示选中范围内各类活动的时间分布。原文录制的大量时间花在渲染工作上,所以后续目标是减少渲染工作量,而不是先假定 JavaScript 的某个算法一定太慢。
展开 Main 轨道,查看主线程火焰图。横轴是录制时间,每条横向色块代表一个事件,越宽意味着持续时间越长;纵向堆叠表示调用关系,在该图的上下文里,上层事件会引发下层事件。宽度不是调用次数,堆叠高度也不是 CPU 使用率百分比。
整段录制可能很长。在包含 FPS、CPU、NET 的 Overview 区域按住鼠标拖动,选中一次 Animation Frame Fired 附近的时间范围。Main 和 Summary 会聚焦到这段选区,避免被整段数据淹没。
原文还提供键盘操作:先点击 Main 的背景或事件,使该区域获得焦点,然后按 W 放大、S 缩小、A 向左移动、D 向右移动。选中事件后,可用方向键选择相邻事件。
五、沿警告找到强制同步布局
观察 Task 和 Layout 事件右上角的红色三角形。这是“需要进一步检查”的提示,不等同于一个完整诊断。原文说明 Task 上的红三角对应长任务;Layout 上的警告则可能指向强制重排。
- 点击
Animation Frame Fired,在 Summary 中查看它的详细信息。 - 点击 Initiated by 附近的链接,定位触发该动画帧事件的上游事件。
- 查看
app.update @链接,它可以带你到对应源代码行。 - 在
app.update下方查找一连串紫色的 Layout 事件,选择其中一个。 - 查看 Summary 中关于 forced reflow 的提示,并沿 Animation Frame Requested 下方的
app.update @链接跳到导致布局的代码。
原文示例的问题是:每一个动画帧里,程序逐个修改方块的样式,又立即读取它在页面中的位置。样式已经变了,浏览器可能需要重新计算布局,才能回答位置查询;之后下一个方块又重复这个过程。大量读写交替造成重复的同步布局,也常被称作 layout thrashing。
减少工作的方向是组织读写顺序:先集中读取需要的几何信息,再集中更新样式,避免每写一次就迫使浏览器回答新的几何问题。这段是对原文机制的解释,不是声称已经替页面提交或验证了代码修复。具体怎样批量读写,还要保持动画逻辑所需要的数据依赖。
六、以相同条件重新录制优化版本
点击演示中的 Optimize,再进行一次性能录制,重复前面的帧、CPU、Summary 与 Main 检查。原文演示的结果是帧表现改善,主线程火焰图中的事件减少,说明浏览器做的工作变少。本文没有复测,所以不提供虚构的耗时、FPS 或改善百分比。
用于比较的方块数量、窗口尺寸、CPU 降速、浏览器版本以及录制时长应尽量一致。若同时改了负载和实现,便难以把差异归因到某一处优化。这是本文为复现补充的比较条件。
原文还特意指出:优化版本依然逐个修改方块的 top 属性,因此并不代表最佳动画实现。进一步优化时,应研究仅影响合成阶段的属性;transform 与 opacity 是官方资料推荐重点了解的方向。具体能否只走合成路径依赖实际页面,仍须以录制验证。
七、把这一流程迁移到自己的页面
本教程围绕一类动画布局瓶颈展开,不能覆盖所有运行期问题。理解 RAIL 有助于确定用户在不同阶段最关心的指标;理解浏览器如何把 HTML、CSS 与 JavaScript 转成像素,才知道每个事件属于哪一段工作。
原文建议继续阅读渲染性能系列,包括 JavaScript 执行优化、缩小样式计算范围、避免复杂布局与反复布局、降低绘制复杂度与绘制面积、使用合成属性并控制图层数量,以及对输入事件做适当调度。若向社区求助,应提供可以复现的页面与必要截图;本文补充建议是在分享前检查轨迹、URL、截图和源代码片段中是否包含个人资料或内部信息。
本篇没有要求执行任意 Console 脚本,也没有可安装的项目依赖。静态检查涵盖教程操作步骤、链接与源文中的性能解释;没有发现硬编码秘密或恶意脚本,不等于对演示网站或浏览器进行了安全审计。
来源与许可
原作者 Kayce Basques,来源 Chrome for Developers,原文链接见文首。原页除另有说明外,正文按 CC BY 4.0 许可,代码示例按 Apache License 2.0 许可。本篇为中文翻译整理;环境说明、测量边界与安全分享提醒为新增内容,示意图为本次原创。
原文的后续阅读与实际文章入口都保留在官方 Next steps 部分;本文没有将这些延伸材料冒充为已执行的测量结果。












暂无评论内容