Skip to content

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 ready420 ms20 ms
200 Item 创建绑定95 ms92 ms
首屏可用540 ms135 ms
p99 Frame120 ms105 ms
峰值内存310 MB305 MB

由此提出两个独立假设:

  1. 冷缓存慢主要来自资源读取/解码;
  2. 冷热都存在的长帧主要来自 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 ms160 ms< 250 ms
p99 Frame120 ms28 ms< 33 ms
峰值内存310 MB220 MB< 250 MB
全部内容650 ms900 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 次无监听增长。

十六、练习答案补充 ​

  1. 若首屏变快但滚动更卡,应检查什么? 后台加载是否与滚动抢 CPU/IO、虚拟 Item reset、图片回调、Layout 和缓存淘汰。
  2. 若 p99 降低但峰值内存上升,能否上线? 需与设备内存预算比较,不能只看流畅;可能因预取/池容量扩大,应调整策略。
  3. 为什么优化报告要写失败路径? 网络与资源失败时可能绕开快路径、卡住 loading 或重复重试,真实用户会遇到。

十七、本课总结 ​

text
真实性能优化是一个实验过程:
复现 → 测量 → 假设 → 修改 → 回归。

十、下一课预告 ​

text
Lesson072|阶段复习:建立可复现、可量化的性能证据链