Inspector 性能分析
Inspector 的 Performance 标签页记录运行中应用的帧,并按时间绘图,定位慢帧及瓶颈。MiniStats显示近期平均值,而 Performance 保留一次采集中的各帧,最多最近 1000 项,便于比较并逐帧查看。
录制
点击圆环包围圆点的录制按钮,开始记录每帧;录制中按钮为红色,再次点击停止。旁边的按钮清空采集。
图表按真实时间覆盖整个采集。每帧宽度对应耗时,慢帧占据更大宽度;两次录制之间等超过一秒的停顿会折叠为标注时长的断开标记。从上到下:
| 图表 | 内容 |
|---|---|
| Frame | 帧间隔。 |
| CPU | 主线程各阶段耗时,包括系统更新、物理、脚本、动画、后更新、渲染和 Inspector 自身。 |
| GPU | 启用 GPU timings 后显示 GPU 帧耗时。 |
| Draw calls | 绘制调用,按引擎可提供的类别细分。 |
| Scripts | 启用 Script timing 后显示各脚本类型耗时,参见脚本计时。 |
| Counters | app.stats.user 中的应用计数器,参见计数器。 |
| Loading | 页面与应用里程碑、资源加载和进行中的请求,参见加载。 |
| Memory | JavaScript 堆、显存及其分类,用相同刻度的线显示。 |
| Resources | 纹理、渲染目标、着色器、缓冲区数量,以及 WebGPU 管线数量。 |
| Events | 每种事件一行,标记出现该事件的帧,参见事件。 |
Frame、CPU 和 GPU 图表中的虚线表示显示刷新间隔。悬停可查看指针下帧的数据及事件。点击图表或分区名称折叠;取消旁边列表某条线的勾选可隐藏,并根据其余数据重新缩放。拖动名称与图表之间的分隔线可调整名称区域宽度。
要查看部分采集:
- 点击一帧,在帧时间线中显示,下方属性视图列出该帧所有记录。
- 在图表上拖动选择多帧,显示平均值、第 95 百分位和最大值;时间线显示平均帧。
- 在图表上滚动缩放,再拖动下方滚动条,或按住 Shift 拖动图表平移。双击恢复整个采集。
- ‹ 和 › 前后移动一帧,« 跳到首帧,» 跟随最新帧。面板聚焦时,方向键移动一帧,按住 Shift 移动十帧,Home 跳到首帧,End 跟随最新帧。
事件
| 事件 | 标记内容 |
|---|---|
| Hitches | 耗时超过帧耗时中位数两倍的帧,不论原因,即用户感受到的卡顿。 |
| Thread blocked | Chromium 报告主线程忙碌至少 50 毫秒的帧,以及执行最久的脚本。它帮助解释慢帧;没有主线程阻塞的卡顿,可能受 GPU、浏览器或显示影响,悬停时会说明。 |
| Lightmaps | 应用通过光照贴图烘焙器进行的烘焙。 |
| Shaders | 着色器编译或创建,以及渲染管线创建。 |
| Heap shrank | JavaScript 堆缩小,即垃圾回收。 |
| Resources | 纹理、渲染目标或缓冲区创建与销毁。 |
| Measures | 应用通过 performance.measure 测量的区间。 |
帧时间线
图表下方的时间线以火焰图显示所选帧的内部时序。
- CPU 行包括更新、后更新、Inspector、渲染及发生的光照贴图烘焙。下方进一步细分物理、动画和渲染阶段;启用脚本计时后,还会按实际执行位置和脚本类型细分 update 与 postUpdate。
- GPU 行显示泛光、景深等效果,下方显示各效果包含的通道及独立通道,参见 GPU 计时。
- Events 行显示主线程长任务和
performance.measure区间,下方列出该帧的里程碑、资源和请求。
悬停条形查看时长,悬停行查看该行全部内容。点击脚本类型会在 Scripts 标签页打开,点击通道或效果会在 Frame graph 打开,点击资源会在 Assets 打开。滚动缩放,拖动滚动条或按 Shift 拖动平移,双击恢复整帧,点击标题可折叠。
下方属性视图列出该帧记录的全部内容,包括瓶颈、各 CPU 阶段和 GPU 通道耗时、脚本、计数器、加载、提交工作、内存、资源和事件。
GPU 计时
启用 GPU timings 记录 GPU 时间。WebGPU 为每个通道计时,并根据帧图归属到相应效果;如果帧图与已计时通道不再对应,所有通道直接放到 GPU 行。连续同名通道共享标签,例如 Downsample ×5,帧详情中仍列出各自耗时。WebGL 只测量整帧。
脚本计时
启用 Script timing,在录制时统计各脚本类型的 update、postUpdate 和 initialize 耗时及调用次数,不包含嵌套调用耗时。CPU 图表会将脚本与其他系统分开,时间线按实际执行位置显示。
Scripts 图表将所选多帧或整个采集中耗时最高的十种脚本堆叠显示,选择峰值区间可突出背后的脚本。其余脚本合并为一条,悬停列出详情。列表下的 ▸ 10 more 每次额外展开十种。要持续跟踪某个脚本,可在帧详情点击 Pin,或在列表中 Shift+单击固定。Alt+单击列表条目可单独显示,再次操作恢复全部。
每次调用计时给应用增加约半微秒开销,计入 Inspector 自身。事件处理、定时器和 Promise 中的时间不计入。未启用跨源隔离的页面,浏览器时钟精度为十分之一毫秒,因此小脚本最好结合多帧分析。
加载
Loading 与图表共用时间轴:
- Milestones 标记页面到达、DOM 就绪、首次绘制、预加载、应用启动和首帧等时刻。
- Assets 显示从发起加载到运行时资源就绪的完整过程:文件请求为实色,后续解析等处理为浅色。颜色表示资源类型,行名称提示中提供图例;失败为红色。
- Requests 显示页面进行中的请求数量。
悬停查看当时正在加载什么,点击资源可在 Assets 标签页查看。
记录应用启动
向 Inspector 传入 record: true,或设置 EntityInspector 脚本的 record 属性,即可从应用首帧开始记录。如果在首帧前,例如 app.init() 之后立即创建 Inspector,还能记录启动过程:
const app = new AppBase(canvas);
app.init(createOptions);
// recording before the first frame records the start of the application too
const inspector = new Inspector(app, { record: true });
app.start();
采集以 Startup 条目开头,包含页面打开到首帧的请求、里程碑、已加载资源及主线程阻塞。详情列出总耗时、加载内容、着色器编译,以及加载最慢资源的请求和处理耗时。它占用 1000 项中的一项,与其他帧一样会被后续数据替换。
可通过代码设置 inspector.recording,围绕应用的某个阶段开始和停止采集:
// once the part to look at has run
inspector.recording = false;
计数器
Counters 绘制各帧结束时 app.stats.user 中的计数器,每个计数器独立一条线和刻度,因为单位由应用定义。帧详情列出具体数值,多帧选择显示平均值、第 95 百分位和最大值。计数器用法见使用 AppStats 分析性能:
// counted afresh each frame
app.on('frameupdate', () => app.stats.user.set('enemies', 0));
// wherever the application counts them
app.stats.user.set('enemies', app.stats.user.get('enemies') + 1);
引擎构建
发布构建只测量整体更新和渲染。Profiler 和调试构建还提供渲染阶段、批处理更新和创建、绘制调用细分、着色器编译和光照贴图烘焙。
Inspector 在应用更新中运行,自身耗时单独显示为 Inspector。关闭 Inspector time 可从 CPU 图表中排除,使刻度仅根据应用自身耗时计算。
复制数据
右键点击标签页名称可复制完整采集及每帧全部记录;右键点击图表、分区名称或列表中的线,可按一帧一行复制该序列,格式为 JSON 或适合表格的 CSV。存在多帧选择时,仅复制所选范围。右键点击图表中的帧可复制该帧,在所选多帧范围内右键可复制汇总数据,在时间线上右键可复制条形数据。