外观
Stage05|Performance
Lesson071|性能实战:完整排查一次页面打开卡顿
Tags: #Creator2.x #Stage05 #PerformanceCase #ProfilingDifficulty: ⭐⭐⭐⭐☆
本课交付物:不是建议清单,而是一份性能报告
最终报告必须回答:
text
谁在什么设备、什么动作下遇到什么症状
基线是多少
主要瓶颈证据是什么
修改了什么
改善了多少
有什么副作用
如何防止回归下面以“商城打开卡顿”为贯穿案例完成全流程。
一、案例背景
用户反馈:
打开商城页面时,页面要等很久,出现后还会卡一下,滑动列表也不流畅。
本课不直接给优化答案,而是完整走一遍证据链。
二、第一步:稳定复现
记录:
text
设备和系统
构建版本
进入路径
网络条件
商城数据量
重复打开次数固定操作:
text
启动 → 登录 → 打开商城 → 等首屏 → 滑动列表 → 返回 → 再打开三、第二步:拆时间点
text
点击按钮
→ loadScene / load 触发
→ 首个资源完成
→ 首屏可见
→ 首屏可交互
→ 列表第一次滑动分别测量,不把所有等待合成一个“加载很慢”。
四、第三步:判断瓶颈维度
假设采样结果:
text
首屏前:IO + 解码较高
首屏创建:CPU 长帧
首次显示:纹理上传和 GPU 尖峰
滑动时:Layout + Label 更新较高
重复打开:内存持续增长这说明不是一个问题,而是多个阶段的成本叠加。
五、第四步:提出分阶段方案
text
首屏前只加载必需资源
首屏后预加载下一页
列表只创建可见 Item
Label 只在数据变化时刷新
场景退出取消监听和异步回调
检查 Texture / Bundle 释放策略每个修改都对应一个观测问题,不能一次改完后失去因果关系。
六、第五步:验证回归
对比表:
| 指标 | 优化前 | 优化后 | 目标 |
|---|---|---|---|
| 首屏可见 | |||
| 首屏可交互 | |||
| 最大帧时间 | |||
| 滑动 P95 | |||
| 内存峰值 | |||
| 重复打开后内存 |
如果只看首屏变快,却让滑动和内存恶化,不能算完成。
七、常见误区
误区一:先把所有图片压小
可能改善内存,却不一定解决 CPU 创建、Layout 或异步竞态。
误区二:一次改十个地方
无法知道哪个修改真正有效。
误区三:只测一次打开
无法发现重复进入后的泄漏和缓存峰值。
误区四:只在开发机验证
目标设备的 CPU、GPU、IO 和内存条件可能完全不同。
八、练习与参考答案
练习
为“打开背包卡顿”设计一份排查计划,至少包含:复现步骤、指标、采样工具、假设、单变量修改和回归数据。
参考答案要点
text
固定设备和背包数据量
→ 记录点击到可交互时间
→ 采样首屏长帧和滑动长帧
→ 分离 IO、CPU、GPU、Memory
→ 检查资源依赖、Item 数量、Layout、Label、监听器
→ 一次改一个因素
→ 重复打开和长时间运行验证十、可复现实验场景
通过 Creator 2.4.x 编辑器建立商城测试页:
text
ShopPanel
├── Banner(大图)
├── CategoryTabs
├── GoodsScrollView
│ └── Content(200 条数据)
└── CurrencyBar测试账号固定 200 件商品,冷缓存和热缓存分别采样。
ShopPerfMarker.ts
ts
const { ccclass } = cc._decorator;
@ccclass
export default class ShopPerfMarker extends cc.Component {
private begin = 0;
markBegin() {
this.begin = Date.now();
cc.log('[SHOP-PERF] click', this.begin);
}
mark(name: string) {
cc.log(
'[SHOP-PERF]',
name,
Date.now() - this.begin
);
}
}标记:
text
click
prefab-ready
instance-created
data-bound
first-screen-ready
all-items-ready十一、第一次采样与假设
示例基线:
| 指标 | 冷缓存 | 热缓存 |
|---|---|---|
| Prefab ready | 420 ms | 20 ms |
| 200 Item 创建绑定 | 95 ms | 92 ms |
| 首屏可用 | 540 ms | 135 ms |
| p99 Frame | 120 ms | 105 ms |
| 峰值内存 | 310 MB | 305 MB |
由此提出两个独立假设:
- 冷缓存慢主要来自资源读取/解码;
- 冷热都存在的长帧主要来自 200 Item 一次性创建、Label/Layout。
不能只优化加载,因为热缓存仍卡。
十二、单变量验证
验证 Item 数
只创建首屏 12 个:
text
p99 105 ms → 24 ms
首屏 135 ms → 48 ms说明创建/布局是主要长帧。
验证资源
保留 200 Item,但 Banner 使用占位图:
text
冷 Prefab/资源阶段改善
热路径变化小说明资源影响冷启动,不是热路径主因。
验证 Overdraw
关闭全屏模糊层后 GPU 稳定帧改善,但打开尖峰仍存在。它是第三个持续成本,不是创建尖峰根因。
十三、最终组合方案
text
点击商城
→ 立即显示骨架屏
→ 并行加载首屏必要资源(限制并发)
→ 创建可见 12 个 Item
→ 首屏可交互
→ 空闲帧预取下一屏数据/图片
→ 虚拟列表复用 Item
→ Banner 失败使用本地回退优化后示例:
| 指标 | 基线 | 优化后 | 目标 |
|---|---|---|---|
| 首屏可用 | 540 ms | 160 ms | < 250 ms |
| p99 Frame | 120 ms | 28 ms | < 33 ms |
| 峰值内存 | 310 MB | 220 MB | < 250 MB |
| 全部内容 | 650 ms | 900 ms | 可后台完成 |
总完成时间可能变长,但用户更早可操作且无长帧。指标选择符合产品目标。
十四、回归矩阵
text
冷/热缓存
弱网/离线/失败
20/200/2000 商品
低端/主流设备
快速开关页面
连续滚动 2 分钟
场景切换后重进
内存警告与后台恢复功能回归包括:商品顺序、价格、图片错位、Item 复用状态、旧回调覆盖、埋点时机。
十五、错误报告示例
错误:
优化了商城,流畅很多。
合格:
Android 低端测试机、Release 包、200 商品、冷缓存。点击到首屏可交互从 p50 540 ms 降至 160 ms;打开阶段 p99 从 120 ms 降至 28 ms;峰值 310 MB 降至 220 MB。全部图片完成由 650 ms 延长到 900 ms,但后台加载不阻塞输入。弱网失败使用默认图,连续开关 20 次无监听增长。
十六、练习答案补充
- 若首屏变快但滚动更卡,应检查什么? 后台加载是否与滚动抢 CPU/IO、虚拟 Item reset、图片回调、Layout 和缓存淘汰。
- 若 p99 降低但峰值内存上升,能否上线? 需与设备内存预算比较,不能只看流畅;可能因预取/池容量扩大,应调整策略。
- 为什么优化报告要写失败路径? 网络与资源失败时可能绕开快路径、卡住 loading 或重复重试,真实用户会遇到。
十七、本课总结
text
真实性能优化是一个实验过程:
复现 → 测量 → 假设 → 修改 → 回归。十、下一课预告
text
Lesson072|阶段复习:建立可复现、可量化的性能证据链