掉帧指的是某一帧没有在规定时间内完成渲染,导致 UI 画面不流畅,产生视觉上的卡顿、跳帧现象。
- Android目标帧率:
- 一般情况下,Android设备的屏幕刷新率是60Hz,即每秒需要渲染60帧(Frame Per Second, FPS)。
- 每帧时间预算:
- 60 FPS → 1秒钟1000ms / 60 ≈ 16.67ms,即每一帧的渲染时间不能超过16.67ms,否则就会出现掉帧。
- 120Hz设备 → 每帧8.33ms预算。
- 掉帧的直观表现:
- 页面滑动、动画卡顿或不流畅。
- 操作有延迟,UI反馈慢。
- 即呈现速度缓慢和帧冻结判断:
- 呈现速度缓慢:在呈现速度缓慢的帧数较多的页面,当超过50%的帧呈现时间超过16毫秒时,用户感官明显卡顿。
- 帧冻结:帧冻结的绘制耗时超过700ms,为严重卡顿问题。
RecyclerView卡顿掉帧测试
续集上篇文章,在 ExampleStartupBenchmark 继续加如以下代码:
java
private final String TARGET_PACKAGE_NAME = "com.xxx.demo";
//...
@Test
public void scrollRecyclerView() {
mBenchmarkRule.measureRepeated(
TARGET_PACKAGE_NAME, // 你的应用包名
Collections.singletonList(new FrameTimingMetric()), // 记录 UI 帧率信息
CompilationMode.DEFAULT, // 默认编译模式
5, // 测试 5 次
scope -> {
Log.d("xaye","scrollRecyclerView test begin");
// **1. 启动 MainActivity**
scope.startActivityAndWait();
try {
Thread.sleep(4000); // 等待界面切换
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// **3. 执行 RecyclerView 滚动**
performRecyclerViewScroll();
return null;
}
);
}
private void performRecyclerViewScroll() {
// 查找 RecyclerView
UiScrollable recyclerView = new UiScrollable(new UiSelector().className("androidx.recyclerview.widget.RecyclerView"));
if (recyclerView.exists()) {
try {
Log.d("xaye","performRecyclerViewScroll");
recyclerView.flingForward(); // 滑动一屏
recyclerView.flingBackward(); // 滑动回去
} catch (Exception e) {
e.printStackTrace();
}
}
}
和前面文章《安卓性能调优之-检测应用启动速度》介绍的一样,先安装 release版本应用,系统没有要求可以是user
版本的,点击 scrollRecyclerView()
左边的运行按钮 “RUN scrollRecyclerView”,然后会重启应用,上面代码中 Thread.sleep(4000)
,是给你留4s时间去点击到 含有 recycleview
的界面,然后就可以自动进行滑动测试了。
点击测试右侧蓝色字体,进入查看详情界面:
可以通过选择CPU波动范围较大的区域和右侧火焰图查看代码具体耗时情况,根据具体代码,进行解决,一般的耗时解决包括:异步图片加载、避免主线程I/O、对象池化等…
测试结果分析
1. frameCount
(帧数量统计)
plaintext
min 131.0, median 210.0, max 218.0
- 含义:测试期间记录的渲染帧总数,反映滚动的持续时间和流畅度。
- min (131):最低帧数,可能出现在滚动启动或停止阶段。
- median (210):中位数帧数,代表典型滚动场景的帧数量。
- max (218):最高帧数,接近连续滚动的理想状态。
分析:
帧数范围较集中(131-218),中位数210表明整体滚动较为稳定,但最低131帧可能存在启动阶段的性能开销。
2. frameDurationCpuMs
(CPU每帧处理耗时百分位)
plaintext
P50 11.6, P90 17.3, P95 20.4, P99 33.8
- 含义:CPU处理单帧所需时间的百分位分布(单位:毫秒)。
- P50 (11.6ms):50%的帧CPU耗时≤11.6ms(优于16.67ms的60fps标准)。
- P90 (17.3ms):90%的帧≤17.3ms(接近60fps临界值)。
- P95 (20.4ms):5%的帧存在轻微卡顿(>16.67ms)。
- P99 (33.8ms):1%的帧明显卡顿(约30fps)。
关键阈值:
- ≤16.67ms:可维持60fps流畅渲染。
- >16.67ms:帧率下降,用户可能感知卡顿。
性能结论:
- 90%的帧满足60fps要求,但顶部5%的帧存在优化空间,尤其是1%的严重卡顿(33.8ms)。
3. Traces: Iteration 0 1 2 3 4
- 含义:测试共执行5次独立迭代,排除偶然性,确保结果可靠性。
- 最佳实践:若某次迭代结果异常(如极端值),需检查是否因系统后台任务干扰。
指标 | 值 | 达标情况 |
---|---|---|
P50 CPU耗时 | 11.6ms | ✅ 优秀 (<<16.67ms) |
P90 CPU耗时 | 17.3ms | ⚠️ 临界 (≈16.67ms) |
P95 CPU耗时 | 20.4ms | ❌ 卡顿 (>16.67ms) |
P99 CPU耗时 | 33.8ms | ❌ 严重卡顿 |