跳转到内容

帧率与卡顿

“平均 60 帧”和“流畅”是两回事。平均 58 的一段采集里,可能每秒都在掉帧,而用户每一次都感觉得到。

iOS 按固定节奏呈现画面 —— 60 Hz 屏是 16.7 毫秒,120 Hz ProMotion 是 8.3 毫秒。节奏到了而这一帧的活没干完,这一帧就掉了。计数器报告的是每秒实际呈现的帧数。

所以在 120 Hz 设备上稳定 60 并不是失败,那是 ProMotion 在静态内容下降到一半刷新率,很正常。真正的失败是用户正在拖动时,120 掉到 40。

在克魔的采集结果里,按这个顺序做:

  1. 找下陷。 曲线急速掉下去又回来的位置。
  2. 记下它发生的时机。 启动时?第一次滑动时?每次加载图片时?
  3. 读同一时刻的其他曲线。 诊断就在这一步。
下陷时的表现 大概率原因
CPU 冲高 主线程上有活 —— 布局、JSON 解析、图片解码、同步读文件
GPU 冲高、CPU 平 渲染瓶颈 —— 过度绘制、模糊、阴影、离屏渲染、层级过多
内存跳升 一次大分配,常见于为了显示缩略图而解码整张原图
网络在动 在错误的线程上等请求
什么都没动 阻塞发生在你的进程之外,或者设备在降频
  • 主线程解码图片。 把一张 4000 像素的照片塞进 200 像素的 cell,整张图都会被解码。显示前先降采样。
  • 名为复用实为重建的 cell。 列表在重建视图而不是回收视图时,CPU 会随滑动速度线性增长。
  • 模糊和阴影。 这两样在桌面 GPU 上很便宜,在手机上很贵。运动中的视图带阴影是经典案例:给它一条明确的 shadowPath。
  • 滑动回调里的同步操作。 拖动过程中碰磁盘或碰网络,一定看得出来。
  • 深层级里的 Autolayout。 约束求解的开销增长快于视图数量。
  • 用你支持的最旧机型。 帧预算固定是 16.7 毫秒;快的芯片会掩盖草率的活,旧的不会。
  • 让设备凉下来。 降频造成的卡顿,改代码是改不掉的。
  • 每次重现同一段交互。 同一个列表、同样距离、同样速度。
  • 在数据线上采。 无线采样自带抖动,和你要抓的抖动分不开。

有些卡顿永远不会出现在 FPS 上:点下去 300 毫秒才响应、动画晚了一拍才起来。看那段交互周围的 CPU 曲线和实时日志 —— 拖动过程中日志输出出现一段长时间空白,往往是你能拿到的最清晰的证据。

性能监控 · 实时日志 · 能耗