加载与卡顿
自动关联目录:加载与卡顿
1. 定位
卡顿(hitch)和"平均帧率低"是两类问题:平均帧率低是持续成本,卡顿是某一帧突然做了很多事。
一句话定位:卡顿的排查核心是"那一帧多做了什么",而不是"整体哪里慢"。
2. 卡顿的常见来源
| 来源 | 说明 | 对应篇 |
|---|---|---|
| 同步加载 | 主线程 LoadObject / LoadSynchronous | 资源加载与异步加载 |
FlushAsyncLoading | 把异步变同步 | 资源加载篇 |
| PSO 首次编译 | 驱动现场编译 | PSO 预缓存 |
| 着色器编译 | 首帧/首现材质 | 材质与着色器编译 |
| GC | 全量可达性分析 | GC 与对象生命周期 |
| 渲染线程同步 | FlushRenderingCommands | 管线与渲染线程 |
| World Partition 单元加载 | 传送/快移 | World Partition |
| 阴影缓存作废尖峰 | VSM 重画大片页 | 虚拟阴影贴图 |
| 动画首播解压 | 首次播放某段动画 | 动画压缩与内存 |
| 资源流式 | 纹理/网格流送 | 资源加载 |
3. 定位工具
| 工具 | 用途 |
|---|---|
stat unitgraph | 看抖动最直观——尖峰一目了然 |
| Unreal Insights | 看那一帧的阻塞栈与任务 |
stat streaming | 流式加载状态 |
stat gc | GC 尖峰(见 GC 篇) |
stat tsr | TSR 的收敛(见 TSR) |
stat PSOPrecache | PSO 预缓存 miss(见 PSO 篇) |
Insights 的 PSOPrecache: Missed / Too Late | 直接看 PSO 造成的卡顿 |
stat unitgraph 是发现卡顿的第一工具——数字看不出抖动,图形一眼看到。
4. 加载屏的正确做法
| 要点 | 说明 |
|---|---|
| 必须等 PSO 预缓存完成 | FShaderPipelineCache::NumPrecompilesRemaining() 归零才放行(见 PSO 篇) |
| 地形等不支持延迟策略的对象要等 | 官方明确:landscape 不适合换默认材质或不渲染 |
| 用流式源预加载 | 传送前先在目标位置放流式源(见 WP 篇) |
Is Streaming Completed | 判断单元是否加载完成 |
| 首启体验要清驱动缓存测 | -clearPSODriverCache(见 PSO 篇) |
最常见的"进游戏后 pop 与卡顿":加载屏没有等 PSO 预缓存就放行了。
5. 代价与权衡
| 手段 | 收益 | 代价 | 什么时候不该用 |
|---|---|---|---|
| 异步加载 | 不阻塞 | 需要持有 handle 与 UPROPERTY 保活(见资源加载篇) | 必须立刻用到的才同步 |
| 加载屏等待 | 消除进场卡顿 | 加载时间变长 | 时间过长要优化加载量而不是取消等待 |
| 预加载(流式源) | 传送不卡 | 提前占用带宽与内存 | 远处不值得预加载 |
| PSO 预缓存 | 消除驱动编译卡顿 | 内存与启动时间(见 PSO 篇) | 几乎都应该开 |
FlushAsyncLoading | 保证就绪 | 强制同步,制造卡顿 | 运行时热路径不该用 |
6. 踩坑与排查
| 坑 | 现象 | 怎么验证 |
|---|---|---|
| 加载屏没等 PSO | 进游戏后 pop + 卡顿 | NumPrecompilesRemaining() 是否纳入逻辑 |
运行时 LoadSynchronous | 主线程卡 | 改为异步 |
调 FlushAsyncLoading | 每帧掉帧 | 搜索代码里所有 Flush |
| 传送不预加载 | 到点一片空白 | 流式源 + Is Streaming Completed |
| 测试没清驱动缓存 | 卡顿测不出 | -clearPSODriverCache |
| GC 周期性尖峰 | 每隔一段时间卡 | stat gc(见 GC 篇) |
| 只测一次 | 偶发卡顿抓不到 | stat unitgraph + Insights 长时间记录 |
| 只测编辑器 | 打包后不同 | 测打包版本 |
7. 排查顺序
1. stat unitgraph 确认是"尖峰"还是"整体慢"
2. 尖峰在什么时候?(进场 / 传送 / 首次出现某物体 / 周期性)
├─ 进场 → PSO 预缓存 + 加载屏等待
├─ 传送 → WP 流式源预加载
├─ 首次出现 → 着色器编译 / PSO / 动画解压
└─ 周期性 → GC / 阴影重缓存
3. Insights 看那一帧的阻塞栈
4. 对应篇深入
5. 复测必须清 PSO 驱动缓存参考
许可协议:CC BY
作者:Davids
本文链接:https://hustjjd.github.io/c6dc2cca.html
更新于:2026年10月10日