外观
iOS 流畅度与帧体验总览
流畅度不是一个 FPS 数字,而是一条从“屏幕实际呈现了什么”到“用户感受到多严重的顿挫”,再到“为什么会发生”的证据链。Perfowl 将这一领域固定为四层:
text
Presentation Facts
↓
Display Performance
↓
Frame Experience
↓
Root Cause Signals对应到实际阅读路径:
text
FrameLifetime / presentation facts
↓
FPS / FrameTime / P95 / Refresh / Jitter
↓
1% Low / TinyJank / Jank / BigJank / Stutter / Smooth
↓
CPU / GPU / I/O / Screenshot / deeper trace1. 一帧画面如何到达屏幕
text
[App]
触控 / 定时器 / 业务逻辑
→ RunLoop
→ Layout / Display
→ Core Animation Commit
↓
[Render Server]
图层树合成与渲染调度
↓
[GPU]
Tiler / Renderer / Frame Buffer
↓
[Display]
VSync / presentation
→ 系统显示管线记录的新 presentation这里最重要的边界是:App Render 不等于最终 Display Presentation 。主线程、Render Server、GPU 都可能影响最终画面,但 Display Performance 关注的是显示管线何时记录新的 presentation;这不是“光子到眼”的物理测量。
2. 流畅度的五个基础维度
| 维度 | 核心指标 | 回答的问题 |
|---|---|---|
| 吞吐 | FPS | 最近一段时间实际产生多少个新画面? |
| 单帧间隔 | FrameTime | 两次连续 presentation 相隔多久? |
| 长尾 | P95 FrameTime | 较差的一批帧到底有多慢? |
| 刷新率 | Refresh Rate | 屏幕此刻实际刷新率是多少? |
| 稳定性 | Frame Pacing Jitter | 帧节奏是否忽快忽慢? |
这五项属于 Display Performance,是“事实与基础度量层”。
3. 体验派生指标
基础帧序列之上,再回答“用户体验损害有多严重”:
| 指标 | 主要用途 |
|---|---|
| 1% Low FPS | 描述最差一小段帧体验下限 |
| TinyJank | 轻微顿挫事件 |
| Jank | 明显卡顿事件 |
| BigJank | 严重停顿事件 |
| Stutter % | 卡顿帧耗时在观察时长中的占比(2026-11-02 起,与 PerfDog 一致) |
| Smooth | 帧间稳定性的实验性综合分 |
这些指标统一放在 Jank、Stutter 与稳帧体验,不再各自重复描述底层采集服务。
4. 推荐测试阅读顺序
text
先看 Display Performance
↓
FrameTime 是否有尖刺?
P95 / Jitter 是否明显恶化?
FPS 与 Refresh 是否符合场景预期?
↓
再看 Jank / Stutter / 1% Low
↓
最后进入 CPU / GPU / I/O 根因诊断如果只是看到一个资源指标升高,例如 CPU 或 GPU 高,不应直接倒推“所以发生了卡顿”;应先确认同一时间窗的画面事实是否真的异常。
5. FPS、FrameTime 与 Refresh Rate 不是一回事
- FPS:单位时间内出现多少个新 presentation;
- FrameTime:两次连续 presentation 的时间间隔;
- Refresh Rate:显示系统当前的刷新频率,单位为 Hz。
例如屏幕可能工作在 60Hz,而页面只产生约 20 个新画面/秒。此时 Refresh Rate = 60Hz、FPS ≈ 20 可以同时成立,并不自动表示性能缺陷。
6. 常见误区
- 低 FPS ≠ 一定性能差:静态页面没有新内容时,低 FPS 或 0 FPS 可能完全正常;
- 高 FPS ≠ 一定不卡:短时间长帧可以被平均 FPS 掩盖;
- FPS ≠ Refresh Rate:内容更新速率和显示器刷新率是两个概念;
- FrameTime ≠ GPU Render Time:它描述 presentation 间隔,不直接等价于某个单一 pipeline 阶段耗时;
- 跨多个 refresh interval ≠ 自动等于 Dropped Frames:低内容更新率本身可能是正常策略;
- Perfowl Jank ≠ Apple Hitch:二者必须按各自公式与语义解释。
7. 测试环境与参考基线
流畅度比较必须先控制场景:相同设备、相近温度、相同操作路径、相同网络条件、明确目标刷新率/ProMotion 状态。60Hz 下的历史 FPS/Jank 阈值只能作为场景参考基线,不应被解释成适用于所有 App、120Hz 游戏或所有交互类型的统一发布标准。
推荐优先使用:
- 同一场景的历史版本基线;
- 同一设备与相同刷新策略;
- FrameTime/P95/Jitter 的分布变化;
- Jank/Stutter 的变化;
- 再结合业务可接受目标制定 Pass/Warn/Fail。
8. 发现异常后怎么查
进入 卡顿诊断与渲染归因,把异常时间窗与:
- APP CPU / CPU Core;
- GPU Renderer / Tiler / Device;
- Disk / Network / Scheduler;
- Thermal / Memory 环境;
- Screenshot Timeline;
进行同窗对齐。相关信号只负责缩小范围,更深的线程栈、Trace 或复现实验负责确认因果。
9. 当前 Display 数据源与证据边界
当前新 Session 的 FPS、FrameTime、P95、Refresh Rate 与 Jitter 已在 Registry / CapturePlan / Realtime / Report / UI 层切到 ActivityTrace / CoreAnimation FrameLifetime。旧 Graphics FPS 与 CoreProfile Presented Frame 仍保留历史 Session、legacy replay 或受控对照价值,但不再承担新 Session 的长期 Display 主采集。
证据需要分层阅读:iOS 17 FrameLifetime source POC 已完成 E4;产品实现已完成 E2;Display-only、Startup + Display、长稳与跨 iOS 版本的完整产品 E4 仍待继续关闭。因此“当前代码已经切源”和“全平台产品 E4 已完成”不是同一句话。
详见: