掉幀指的是某一幀沒有在規定時間內完成渲染,導致 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 繼續加如以下代碼:
private final String TARGET_PACKAGE_NAME = "com.xxx.demo";//...@Testpublic 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() {// 查找 RecyclerViewUiScrollable 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
(幀數量統計)
min 131.0, median 210.0, max 218.0
- 含義:測試期間記錄的渲染幀總數,反映滾動的持續時間和流暢度。
- min (131):最低幀數,可能出現在滾動啟動或停止階段。
- median (210):中位數幀數,代表典型滾動場景的幀數量。
- max (218):最高幀數,接近連續滾動的理想狀態。
分析:
幀數范圍較集中(131-218),中位數210表明整體滾動較為穩定,但最低131幀可能存在啟動階段的性能開銷。
2. frameDurationCpuMs
(CPU每幀處理耗時百分位)
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 | ? 嚴重卡頓 |