帧率与卡顿
“平均 60 帧”和“流畅”是两回事。平均 58 的一段采集里,可能每秒都在掉帧,而用户每一次都感觉得到。
这个数字是什么
Section titled “这个数字是什么”iOS 按固定节奏呈现画面 —— 60 Hz 屏是 16.7 毫秒,120 Hz ProMotion 是 8.3 毫秒。节奏到了而这一帧的活没干完,这一帧就掉了。计数器报告的是每秒实际呈现的帧数。
所以在 120 Hz 设备上稳定 60 并不是失败,那是 ProMotion 在静态内容下降到一半刷新率,很正常。真正的失败是用户正在拖动时,120 掉到 40。
看下陷,不看平均
Section titled “看下陷,不看平均”在克魔的采集结果里,按这个顺序做:
- 找下陷。 曲线急速掉下去又回来的位置。
- 记下它发生的时机。 启动时?第一次滑动时?每次加载图片时?
- 读同一时刻的其他曲线。 诊断就在这一步。
| 下陷时的表现 | 大概率原因 |
|---|---|
| CPU 冲高 | 主线程上有活 —— 布局、JSON 解析、图片解码、同步读文件 |
| GPU 冲高、CPU 平 | 渲染瓶颈 —— 过度绘制、模糊、阴影、离屏渲染、层级过多 |
| 内存跳升 | 一次大分配,常见于为了显示缩略图而解码整张原图 |
| 网络在动 | 在错误的线程上等请求 |
| 什么都没动 | 阻塞发生在你的进程之外,或者设备在降频 |
先查这几件事
Section titled “先查这几件事”- 主线程解码图片。 把一张 4000 像素的照片塞进 200 像素的 cell,整张图都会被解码。显示前先降采样。
- 名为复用实为重建的 cell。 列表在重建视图而不是回收视图时,CPU 会随滑动速度线性增长。
- 模糊和阴影。 这两样在桌面 GPU 上很便宜,在手机上很贵。运动中的视图带阴影是经典案例:给它一条明确的 shadowPath。
- 滑动回调里的同步操作。 拖动过程中碰磁盘或碰网络,一定看得出来。
- 深层级里的 Autolayout。 约束求解的开销增长快于视图数量。
- 用你支持的最旧机型。 帧预算固定是 16.7 毫秒;快的芯片会掩盖草率的活,旧的不会。
- 让设备凉下来。 降频造成的卡顿,改代码是改不掉的。
- 每次重现同一段交互。 同一个列表、同样距离、同样速度。
- 在数据线上采。 无线采样自带抖动,和你要抓的抖动分不开。
有些卡顿永远不会出现在 FPS 上:点下去 300 毫秒才响应、动画晚了一拍才起来。看那段交互周围的 CPU 曲线和实时日志 —— 拖动过程中日志输出出现一段长时间空白,往往是你能拿到的最清晰的证据。
