各位戰士,歡迎來到第十七天的戰場。在前一天的偵查任務中,我們學會了使用 Profile GPU Rendering 來發現那些飛越 16ms 生命線的「紅色警報」。我們知道了**「何時」發生了 Jank,但我們仍然不完全清楚「為何」**發生。
Profile GPU Rendering 就像是戰場上的哨兵,他能大喊「有敵人!」,但我們需要更強大的工具來回答接下來的問題:敵人是誰?有多少人?他們攜帶了什麼武器?
今天,我們將學習使用 Android 平台最強大的性能分析工具——Perfetto(其前身為 Systrace)。它不是望遠鏡,而是軍事衛星,能為我們拍下整個戰場在卡頓瞬間的、精確到微秒的「活動快照」。
簡單來說,當你開始錄製一段 Trace(追蹤記錄)時,Android 系統會像一個高速攝影機,記錄下這段時間內系統各個部分的所有關鍵活動,包括:
Perfetto 是一個現代化的、基於網頁的 Trace 視覺化工具,它可以打開並解析這些由系統產生的複雜 Trace 檔案,用直觀的時間軸圖表呈現在我們面前。
捕獲 Trace 的方式有幾種,我們介紹兩種最常用的。
這是最簡單、整合度最高的方式,適合絕大多數開發場景。
當卡頓難以在連接電腦時穩定重現,可以使用此方法。
gfx
(圖像)、view
(視圖系統)、sched
(CPU 調度)、input
(輸入事件)。.perfetto-trace
檔案,將它分享到你的電腦上。無論使用哪種方式,你最終都會看到一個類似的、充滿泳道圖的時間軸介面。它看起來很嚇人,但對於抓 Jank,我們只需要關注幾個關鍵部分:
找到你的應用程式:在左側的搜尋框中,輸入你 App 的套件名稱 (Package Name),Perfetto 會高亮顯示與你 App 相關的所有進程。
關注 FrameTimeline
:在你的應用進程下,找到名為 FrameTimeline
或 Actual Timeline
的泳道。
分析 UI Thread:這永遠是你的重點偵查對象。
doFrame
或 performTraversals
的任務。這就是 Android 系統在一幀內繪製畫面的主要工作。onMeasure
, onLayout
, onDraw
等任務。如果其中任何一個任務佔據了過長的時間(例如超過 10ms),它就是導致卡頓的直接原因。分析 RenderThread:UI Thread 的下方通常是 RenderThread。分析方法相同,檢查是否有異常耗時的任務。
為了讓 Trace 更清晰,你可以在你的程式碼中加入自訂的標籤。
import android.os.Trace
// 在 RecyclerView.onBindViewHolder 或其他你懷疑耗時的方法中
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
Trace.beginSection("MyAdapter.onBindViewHolder") // 開始標記
// ... 你的原有耗時邏輯 ...
Trace.endSection() // 結束標記
}
加上這段程式碼後,當你再次抓取 Trace 時,就能在 UI Thread 的時間軸上看到一個名為 "MyAdapter.onBindViewHolder" 的區塊,讓你一眼就看出是哪段程式碼出了問題。
今天,我們掌握了性能分析的終極武器——Perfetto。我們學會了:
錄製 Trace:透過 Android Studio 或手機內建功能來捕獲系統活動快照。
定位 Jank:在 FrameTimeline 中找到代表掉幀的紅色/黃色方塊。
分析根源:在 UI Thread 中,找到與掉幀方塊對應時間點的、耗時過長的任務(如 onDraw 或自訂標籤)。
我們的作戰流程已經清晰:用視覺化工具發現煙霧,再用 Perfetto 的衛星快照定位火源。
既然我們已經擁有了精準定位敵人的能力,從明天開始,我們將學習各種具體的「殲滅戰術」。首先要攻克的,就是最常見的敵人之一:因佈局複雜導致的渲染性能問題。
我們明天見!