Jank、BigJank 与卡顿率说明
PerfKitty 使用逐帧 FrameTime(帧耗时)识别画面卡顿,并提供 Jank、BigJank 和卡顿率(Stutter)指标。Android 与 iOS 使用相同的判定与统计方式,便于在不同设备和平台之间理解测试结果。
FrameTime 是什么
FrameTime 表示一帧画面从上一帧到当前帧所经历的时间,单位为毫秒(ms)。帧耗时越长,画面更新间隔越大,用户越容易感受到停顿或跳帧。
例如,在理想的 60 FPS 场景中,一帧大约需要 16.67 ms。如果某一帧突然耗时 100 ms,画面会较长时间没有更新,但是否记为 Jank 还需要同时结合前 3 帧的平均耗时判断。
Jank 判定
当前帧需要同时满足以下两个条件,才会被记为一次 Jank:
- 当前帧 FrameTime 大于前 3 帧平均 FrameTime 的 2 倍。
- 当前帧 FrameTime 大于
1000 / 24 × 2,约为83.33 ms。
可以写成:
当前帧 FrameTime > 前 3 帧平均 FrameTime × 2
并且
当前帧 FrameTime > 83.33 ms
第一项用于识别相对于近期画面节奏突然变慢的帧,第二项用于过滤绝对耗时较低、通常不构成明显卡顿的波动。两个条件必须同时成立。
BigJank 判定
当前帧需要同时满足以下两个条件,才会被记为一次 BigJank:
- 当前帧 FrameTime 大于前 3 帧平均 FrameTime 的 2 倍。
- 当前帧 FrameTime 大于
1000 / 24 × 3,即125 ms。
可以写成:
当前帧 FrameTime > 前 3 帧平均 FrameTime × 2
并且
当前帧 FrameTime > 125 ms
BigJank 表示更严重的长帧。满足 BigJank 条件的帧通常也满足 Jank 条件,因此可以把 BigJank 理解为 Jank 中较严重的一部分。
卡顿率如何计算
卡顿率用于表示整个测试期间有多少时间消耗在 Jank 帧上:
卡顿率(%)= 所有 Jank 帧的 FrameTime 之和 / 测试总时长 × 100%
例如,一次测试持续 10 秒,被判定为 Jank 的帧耗时分别为 100 ms、130 ms 和 200 ms:
Jank 总耗时 = 100 + 130 + 200 = 430 ms
测试总时长 = 10 × 1000 = 10000 ms
卡顿率 = 430 / 10000 × 100% = 4.3%
这里的分母始终是完整测试时长,而不是只包含 Jank 的采样区间。测试时间越长且流畅区间越多,相同 Jank 总耗时对应的卡顿率就越低。
Jank 次数与卡顿率的区别
Jank 次数和卡顿率描述的是不同方面:
- Jank 次数反映测试期间出现了多少个卡顿帧。
- BigJank 次数反映其中有多少个帧属于更严重的长时间卡顿。
- 每分钟 Jank/BigJank按测试时长归一化,适合比较时长不同的测试。
- 卡顿率反映 Jank 帧占用了多少测试时间,同时考虑卡顿次数和每次卡顿的持续时间。
两次测试可能具有相同的 Jank 次数,但如果其中一次包含更长的 Jank 帧,它的卡顿率通常更高。分析性能问题时,建议同时查看次数、卡顿率、FrameTime 和 FPS 曲线。
测试与对比建议
- 比较不同版本或设备时,尽量保持测试场景、操作步骤和测试时长一致。
- 测试开始后应覆盖完整的目标场景,避免只截取发生卡顿的短区间,否则卡顿率会被放大。
- 启动、切换场景、资源加载和网络等待可能产生长帧,应结合时间点和业务操作判断是否符合预期。
- 某个平台或设备无法提供有效逐帧 FrameTime 时,Jank、BigJank 或卡顿率可能缺失;缺失值不应被理解为
0。 - 曲线中的单秒卡顿率用于定位问题发生的时间,概况中的卡顿率用于评价整场测试,两者的观察范围不同。