Android 會從應用程式產生影格並將其顯示在螢幕上以呈現 UI。如果應用程式的 UI 顯示速度緩慢,系統會強制略過影格。當這種情況發生時,使用者會在螢幕上看到週期性閃爍的情形,稱為資源浪費。
發生資源浪費時,通常是因為 UI 執行緒上的部分減速或封鎖非同步呼叫 (在大多應用程式中,是主要執行緒) 所致。您可以透過系統追蹤記錄找出問題。
在 Android 12 及以上版本上偵測資源浪費
對於搭載 Android 12 (API 級別 31) 或以上版本的裝置,CPU 分析器的「Display」(顯示) 窗格下方的「Janky frames」(卡頓的影格) 軌跡會顯示已擷取的追蹤記錄。
如何偵測資源浪費:
在 Android Studio 中,依序選取「View」(檢視) >「Tool Windows」(工具視窗) >「Profiler」(分析器),或按一下工具列中的「Profile」(設定檔) 圖示
。
如果畫面顯示「Select Deployment Target」(選取部署目標) 對話方塊,請選擇要用來部署應用程式的裝置,以便進行剖析。如果您已透過 USB 連線裝置,但清單中未列出該裝置,請確認您已啟用 USB 偵錯。
按一下 CPU 時間軸中任一處,即可開啟 CPU 分析器。
在 CPU 分析器的設定選單中,選取「System Trace」(系統追蹤),然後按一下「Record」(記錄)。與應用程式互動完畢後,按一下「Stop」(停止)。
「Display」(顯示) 底下應該會顯示「Janky frames」(卡頓影格) 軌跡。根據預設,分析器只會將卡頓的影格列為調查的候選項目。在每個卡頓影格中,紅色部分會醒目顯示影格超過轉譯期限的時間區段。
找到某個卡頓影格後,在上面按一下;或者,您也可以按下「M」來調整縮放,將焦點移至所選影格上。這些執行緒中的相關事件會醒目顯示:主執行緒、RenderThread 和 GPU 完成數。
您可以選擇查看所有影格或轉譯時間的詳細資訊,只要分別勾選「All Frames」(所有影格) 和「Lifecycle」(生命週期) 核取方塊即可。
在 Android 11 上偵測資源浪費
對於使用 Android 11 (API 級別 30) 的裝置,CPU 分析器的「Frame Lifecycle」(影格生命週期) 區段會顯示已擷取的追蹤記錄。
「Frame Lifecycle」(影格生命週期) 區段包含圖層名稱和四個軌跡。每個軌跡都代表影格轉譯管線中的一個階段。「Frame Lifecycle」(影格生命週期) 元素如下所示:
- 「Frame Lifecycle」(影格生命週期) (層級名稱):區段標題包含層級名稱 (用括號括起來)。層級是單一的構成單位。
- 「Application」(應用程式):此軌跡顯示將緩衝區被應用程式退出佇列及重新排入佇列的時間。這通常會對應至
RenderThread
中的追蹤事件。 - 「Wait for GPU」(等待 GPU):這個軌跡會顯示 GPU 擁有緩衝區的時長。此為從緩衝區發送到 GPU 至 GPU 完成其在緩衝區工作的時間。但這並不表示 GPU 在這段期間內只會在這個緩衝區中作業。如要進一步瞭解 GPU 在指定時間範圍內的運作方式,建議您使用 Android GPU 檢查器。
- 「Composition」(組成):這個軌跡顯示的時間為,從 SurfaceFlinger 鎖定到緩衝區,後將其發送至組成,再從緩衝區發送至螢幕。
- 「Frames on Display」(顯示影格數):這個軌跡會顯示影格停留在畫面上的時間長度。
「Frame Lifecycle」(影格生命週期) 區段會說明影格緩衝區如何在轉譯管道的不同階段之間移動。影格會依影格編號進行顏色編碼,方便您更容易追蹤特定的影格。
Android Studio 也會在「All Frames」(所有影格) 分頁中以表格格式顯示追蹤記錄中的所有影格。
「Frame #」(影格數)、「Application」(應用程式)、「Wait for GPU」(等待 GPU)和「Composition」(組成)資料欄分別代表與上述「Frame Lifecycle」(影格生命週期) 區段內軌跡相同的資料。「Frame Duration」(影格持續時間) 資料欄代表從「Application」(應用程式) 開頭到「Frames on Display」(顯示影格數) 開頭的時間。這本質上是端到端顯示影格所需的時間。
您可以按照任何資料欄排序影格表格,以快速找到最短或最長的影格。表格也支援分頁控制選項,可協助您瀏覽數百個影格。
如要在 Android 11 上偵測及調查資源浪費,請按照下列步驟操作:
依「Application」(應用程式) 欄遞減排序「All Frames」(所有影格) 表格,因此最耗時的影格優先顯示。
查看最長的執行時間,然後選取表格列。這會在左側時間軸檢視畫面中放大所選影格。
在「Frame Lifecycle」(影格生命週期) 和「Threads」(執行緒) 區段中尋找相關的執行緒。
在 Android 10 及以下版本上偵測資源浪費
對於使用 Android 10 (API 級別 29) 及以下版本的裝置,相關 OS 圖形管道資訊會顯示在 CPU 分析器系統追蹤記錄上名為「Display」(顯示) 的單一區段中。
- 影格:本節顯示應用程式中的 UI 執行緒和
RenderThread
追蹤記錄事件。超過 16 毫秒的事件會呈紅色,以醒目顯示潛在卡頓影格,因為其已超過顯示 60 個每秒影格數 (fps) 的期限。 - 「SurfaceFlinger」:本節顯示 SurfaceFlinger 如何處理畫面緩衝區。SurfaceFlinger 是一種系統處理程序,用來傳送要顯示的緩衝。
- 「VSYNC」:本節顯示 VSYNC,這是同步處理顯示管道的信號。這個軌跡會顯示 VSYNC-app 信號,在應用程式啟動太晚時顯示。原因通常是因為 UI 執行緒處於忙碌狀態。當您使用動畫功能時,螢幕會有可見的閃爍畫面,並在動畫或捲動完成前加上額外輸入延遲時間。由於顯示頻率可能會超過每秒 60 次,或以可變速率顯示,因此這對於查看高刷新率的螢幕尤其重要。
- BufferQueue:這個部分顯示有多少影格已排入緩衝區,正在等待 SurfaceFlinger 使用。如果是部署至執行 Android 9 (API 級別 28) 或以上版本裝置的應用程式,此軌跡顯示應用程式介面 BufferQueue (
0
、1
、或2
) 的緩衝區數量。BufferQueue 能協助您瞭解圖片緩衝區在 Android 圖形元件之間移動時的狀態。例如,2
表示應用程式目前處於三重緩衝處理,造成額外的輸入延遲時間。
「Display」(顯示) 部分會提供實用的信號來偵測潛在的資源浪費,例如當 UI 執行緒或 RenderThread
耗時超過 16 ms 時。如要調查導致資源浪費的確切詳細資料,您可以探測「Threads」(執行緒) 部分,其中顯示與 UI 轉譯相關的執行緒。
在上圖中,「Threads」(執行緒) 區段會顯示 UI 執行緒 (java.com.google.samples.apps.iosched
)、RenderThread
和 GPU completion
執行緒。這些是與 UI 顯示相關的執行緒,可能會導致資源浪費。
如要在 Android 10 或以下版本中偵測資源浪費,請按照下列步驟操作:
查看「Display」(顯示) 中的「Frames」(影格) 軌跡。紅框是調查的候選項。
找到可能卡頓的影格時,按下
W
或按住 Control (macOS 為 Command) 並捲動滑鼠滾輪來放大畫面。繼續放大,直到開始在 UI 執行緒和RenderThread
中看到追蹤事件為止。在上圖中,UI 執行緒呼叫
Choreographer
以協調動畫、檢視版面配置、圖片繪圖及相關程序時,會顯示Choreographer#doFrame
。RenderThread
組成並發出對 GPU 的實際繪圖指令時,會顯示DrawFrames
。如果您看到特別長的追蹤記錄事件,可以進一步縮小,找出導致顯示速度變慢的原因。上圖顯示了 UI 執行緒中的
inflate
,這表示應用程式正在耗時加載版面配置。當您放大其中一個inflate
事件時,您可準確瞭解每個 UI 元件花費的時間,如下圖所示。
瞭解詳情
如要進一步瞭解如何減少資源浪費,請參閱資源浪費的常見來源。