一、卡頓原因
屏幕1秒60幀,平均每幀16.6毫秒,如果代碼實(shí)現(xiàn)不佳,或者過(guò)于復(fù)雜,導(dǎo)致一幀繪制時(shí)間大于16.6毫秒,則無(wú)法完成繪制,造成丟幀,連續(xù)出現(xiàn)掉幀,在現(xiàn)象上表現(xiàn)為卡頓。
二、App啟動(dòng)時(shí)間
1、方法1
adb shell am start -W com.zhoupushuju.zhouyi/com.rnmobx.MainActivity
結(jié)果
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.zhoupushuju.zhouyi/com.rnmobx.MainActivity }
Status: ok
LaunchState: COLD
Activity: com.zhoupushuju.zhouyi/com.rnmobx.MainActivity
TotalTime: 931
WaitTime: 934
Complete
- LaunchState:?jiǎn)?dòng)方式,此為冷啟動(dòng)
- Activity:?jiǎn)?dòng)頁(yè)面
- TotalTime:?jiǎn)?dòng)Activity的總耗時(shí)
- WaitTime:?jiǎn)?dòng)Activity的總耗時(shí)+少量的系統(tǒng)耗時(shí)
2、方法2
adb logcat -b all | grep am_activity_launch_time
結(jié)果
[0,78748358,com.zhoupushuju.zhouyi/com.rnmobx.MainActivity,931]
三、AndroidStudio Profile使用
1、在 Android 12 及更高版本上檢測(cè)卡頓情況
對(duì)于搭載 Android 12(API 級(jí)別 31)或更高版本的設(shè)備,CPU 性能分析器中 Display 窗格下的 Janky Frameworks 軌道中會(huì)顯示捕獲的軌跡。
如需檢測(cè)卡頓情況,請(qǐng)按以下步驟操作:
-
在 Android Studio 中,依次選擇 View > Tool Windows > Profiler,或點(diǎn)擊工具欄中的 Profile 圖標(biāo)
image.png如果 Select Deployment Target 對(duì)話框顯示提示,請(qǐng)選擇要將您的應(yīng)用部署到哪個(gè)設(shè)備以進(jìn)行性能分析。如果您已通過(guò) USB 連接設(shè)備但系統(tǒng)未列出該設(shè)備,請(qǐng)確保您已啟用 USB 調(diào)試。
點(diǎn)擊 CPU 時(shí)間軸上的任意位置以打開(kāi) CPU 性能分析器。
從 CPU 性能分析器的配置菜單中選擇 System Trace,然后點(diǎn)擊 Record。完成與應(yīng)用的交互后,點(diǎn)擊 Stop。
-
您應(yīng)該會(huì)在 Display 下方看到 Janky frames 軌道。默認(rèn)情況下,性能分析器只會(huì)將卡頓幀顯示為有待調(diào)查的候選對(duì)象。在每個(gè)卡頓幀中,紅色部分突出顯示了相應(yīng)幀超出其渲染截止時(shí)間的時(shí)長(zhǎng)。
image.png -
發(fā)現(xiàn)卡頓幀后,點(diǎn)擊該幀;可根據(jù)需要按 M 鍵調(diào)整縮放程度以聚焦到所選幀。相關(guān)事件會(huì)在以下線程中突出顯示:主線程、RenderThread 和 GPU completion。
image.png -
通過(guò)選中或取消選中 All Frames 和 Lifecycle 復(fù)選框,您可以根據(jù)需要查看所有幀或呈現(xiàn)時(shí)間的細(xì)分?jǐn)?shù)據(jù)。
image.png
2、在Android 11上檢測(cè)卡頓情況
對(duì)于搭載 Android 11(API 級(jí)別 30)的設(shè)備,CPU 性能分析器的 Frame Lifecycle 部分會(huì)顯示捕獲的軌跡。

Frame Lifecycle 部分包含層名稱和四個(gè)軌跡。每個(gè)軌跡分別代表幀呈現(xiàn)流水線中的一個(gè)階段。Frame Lifecycle 元素如下:
- Frame Lifecycle (層名稱):該部分的標(biāo)題包含用括號(hào)括起來(lái)的層名稱。層是單個(gè)組合單元。
-
Application:此軌跡顯示從緩沖區(qū)被應(yīng)用移出隊(duì)列到重新回到隊(duì)列的時(shí)間。這通常對(duì)應(yīng)于
RenderThread中的軌跡事件。 - Wait for GPU:此軌跡顯示 GPU 擁有相應(yīng)緩沖區(qū)的時(shí)長(zhǎng)。該時(shí)長(zhǎng)指的是,從相應(yīng)緩沖區(qū)的內(nèi)容被發(fā)送至 GPU,到 GPU 利用相應(yīng)緩沖區(qū)的內(nèi)容完成其工作,期間所經(jīng)歷的時(shí)間。這并不表示 GPU 在此期間僅使用相應(yīng)緩沖區(qū)的內(nèi)容工作。如需詳細(xì)了解給定時(shí)間內(nèi) GPU 執(zhí)行的工作,您可能需要使用 Android GPU 檢查器。
- Composition:此軌跡顯示,從 SurfaceFlinger 占有相應(yīng)緩沖區(qū)并發(fā)送相應(yīng)緩沖區(qū)的內(nèi)容以進(jìn)行合成,到相應(yīng)緩沖區(qū)的內(nèi)容被發(fā)送到顯示屏,期間所經(jīng)歷的時(shí)間。
- Frames on display:此軌跡顯示相應(yīng)幀在屏幕上的時(shí)長(zhǎng)。
Frame Lifecycle 部分說(shuō)明了幀緩沖區(qū)在呈現(xiàn)流水線的不同階段之間的切換方式。幀按幀號(hào)進(jìn)行顏色編碼,以便更輕松地跟蹤特定幀。
Android Studio 還會(huì)在 All Frames 標(biāo)簽頁(yè)中以表格格式顯示軌跡中的所有幀。

Frame #、Application、Wait for GPU 和 Composition 列表示的數(shù)據(jù)與上方 Frame Lifecycle 部分的軌跡表示的數(shù)據(jù)一樣。Frame Duration 列表示從 Application 開(kāi)始到 Frames on Display 開(kāi)始所經(jīng)歷的時(shí)間。這本質(zhì)上是端到端呈現(xiàn)幀的時(shí)長(zhǎng)。
您可以按任意列對(duì)“Frames”表進(jìn)行排序,以便快速找到最短或最長(zhǎng)的幀。該表還支持分頁(yè)控件,您可以借助這些控件瀏覽數(shù)以百計(jì)的幀。
如需在 Android 11 上檢測(cè)和調(diào)查卡頓情況,請(qǐng)按以下步驟操作:
-
按 Application 列對(duì) All Frames 表進(jìn)行降序排序,使耗時(shí)最長(zhǎng)的幀首先顯示。
image.png -
找到運(yùn)行時(shí)間最長(zhǎng)的幀,然后選擇表中的一行。這將在左側(cè)的時(shí)間軸視圖中放大所選的幀。
image.png -
在 Frame Lifecycle 和 Threads 部分查找相關(guān)線程。
image.png
3、在Android 10及更低版本上檢測(cè)卡頓情況
對(duì)于搭載 Android 10(API 級(jí)別 29)及更低版本的設(shè)備,相關(guān)的操作系統(tǒng)圖形管道信息會(huì)顯示在 CPU 性能分析器系統(tǒng)軌跡中的單個(gè)部分,稱為 Display。

-
Frames:此部分顯示應(yīng)用中的界面線程和
RenderThread軌跡事件。時(shí)長(zhǎng)超過(guò) 16 毫秒的事件會(huì)以紅色表示,以突出顯示潛在的卡頓幀,因?yàn)樗鼈兂隽艘?60 幀/秒 (fps) 的速度進(jìn)行呈現(xiàn)的截止時(shí)間。 - SurfaceFlinger:此部分顯示 SurfaceFlinger 處理幀緩沖區(qū)的時(shí)間。SurfaceFlinger 是負(fù)責(zé)將緩沖區(qū)內(nèi)容發(fā)送到顯示屏的系統(tǒng)進(jìn)程。
- VSYNC:此部分顯示 VSYNC,這是一個(gè)表示與顯示流水線保持同步的信號(hào)。該軌跡會(huì)顯示 VSYNC-app 信號(hào),這個(gè)信號(hào)會(huì)在應(yīng)用啟動(dòng)時(shí)間過(guò)晚時(shí)顯示。通常情況下,發(fā)生這種情況是因?yàn)榻缑婢€程處于忙碌狀態(tài)。在動(dòng)畫(huà)播放期間,它會(huì)導(dǎo)致屏幕上出現(xiàn)可見(jiàn)的閃爍,并且在動(dòng)畫(huà)或滾動(dòng)完成之前,會(huì)持續(xù)帶來(lái)額外的輸入延遲。對(duì)于刷新率較高的顯示屏,尤其要注意查看該軌跡,因?yàn)榕c刷新率為 60 次/秒或刷新率可變的顯示屏相比,這種顯示屏更容易出現(xiàn)此類問(wèn)題。
-
BufferQueue:此部分顯示有多少幀緩沖區(qū)在排隊(duì)等待 SurfaceFlinger 使用。對(duì)于部署到搭載 Android 9(API 級(jí)別 28)或更高版本的設(shè)備的應(yīng)用,此軌跡顯示應(yīng)用 surface BufferQueue 的緩沖區(qū)計(jì)數(shù)(
0、1或2)。BufferQueue 可幫助您了解圖像緩沖區(qū)在 Android 圖形組件之間切換時(shí)的狀態(tài)。例如,值2表示應(yīng)用當(dāng)前處于三重緩沖狀態(tài),這會(huì)導(dǎo)致額外的輸入延遲。
Display 部分會(huì)提供有助于檢測(cè)潛在卡頓的實(shí)用信號(hào),例如何時(shí)界面線程或 RenderThread 的用時(shí)超過(guò) 16 毫秒。若要調(diào)查導(dǎo)致卡頓的確切細(xì)節(jié),您可以查看 Threads 部分,其中會(huì)顯示與界面呈現(xiàn)有關(guān)的線程。

在上圖中,Threads 部分顯示了界面線程 (java.com.google.samples.apps.iosched)、RenderThread 和 GPU completion 線程。這些線程與界面呈現(xiàn)有關(guān),可能是導(dǎo)致卡頓的原因。
如需在 Android 10 或更低版本上檢測(cè)卡頓情況,請(qǐng)執(zhí)行以下操作:
-
查看 Display 中的 Frames 軌跡。紅色幀是要調(diào)查的候選對(duì)象。
image.png -
發(fā)現(xiàn)可能存在卡頓的幀后,請(qǐng)按
W,或在按住 <kbd style="box-sizing: inherit;">Control</kbd> 鍵(在 macOS 設(shè)備上,則按住 <kbd style="box-sizing: inherit;">Command</kbd> 鍵)的同時(shí)滾動(dòng)鼠標(biāo)滾輪,以便進(jìn)行放大。繼續(xù)放大,直到您看到界面線程和RenderThread中的軌跡事件。
image.png在上圖中,
Choreographer#doFrame顯示了界面線程何時(shí)調(diào)用Choreographer來(lái)協(xié)調(diào)動(dòng)畫(huà)、視圖布局、圖像繪制和相關(guān)進(jìn)程。DrawFrames顯示了RenderThread何時(shí)形成并向 GPU 發(fā)出實(shí)際繪制命令。 如果您發(fā)現(xiàn)某個(gè)軌跡事件特別長(zhǎng),可以進(jìn)一步放大,以便找出可能導(dǎo)致呈現(xiàn)速度緩慢的原因。上圖顯示了界面線程中的
inflate,這意味著應(yīng)用正在花時(shí)間膨脹布局。當(dāng)您放大其中一個(gè)inflate事件時(shí),可以確切了解每個(gè)界面組件花費(fèi)的時(shí)間,如下所示。









