iT邦幫忙

2025 iThome 鐵人賽

DAY 2
0
Mobile Development

Android 性能戰爭:從 Profiler 開始的 30 天優化實錄系列 第 2

# Day 2:【CPU Profiler】初探:找出耗時的兇手

  • 分享至 

  • xImage
  •  

各位戰士,早安!在昨天的戰前宣言後,我們士氣高昂。今天,我們將不再紙上談兵,而是要拿起武器,打響性能戰爭的第一槍。

我們的首要目標是 CPU——應用的「大腦」。當使用者感覺到「卡頓」時,十之八九是 CPU 在某個時刻被繁重的任務拖垮了。而我們的任務,就是利用 CPU Profiler 這把精準的手術刀,找出藏在程式碼深處的耗時兇手。

進入作戰位置:開啟 CPU Profiler

首先,確保你的應用程式正在一個實體設備或模擬器上以除錯模式 (Debug Mode) 運行。然後,在 Android Studio 的底部工具列找到並點擊 Profiler 標籤。

打開 Profiler 視窗後,你會看到一個時間線,顯示著你 App 的 CPU、記憶體和網路活動。點擊 CPU 時間線的任何地方,即可進入 CPU Profiler 的詳細視圖。

選擇你的偵查策略:Sampled vs. Instrumented

在開始記錄之前,我們必須選擇一種偵查策略。CPU Profiler 提供了多種記錄配置,其中最常用於應用程式碼分析的是兩種:

  1. Java/Kotlin Method Sample (採樣)

    • 原理:Profiler 會以非常高的頻率(例如每秒 1000 次)對 App 的呼叫堆疊(Call Stack)進行「快照」。如果一個函式在多次快照中都出現,就代表它可能運行了很長時間。

    • 優點:性能開銷較低,對 App 的運行影響較小,能反映出真實世界的運行情況。

    • 缺點:如果一個函式執行時間很短,但被頻繁呼叫,它可能在快照間隙被「錯過」。

    • 適用場景首選策略。適合用來偵查一個未知問題,對 App 進行宏觀的性能分析。

  2. Java/Kotlin Method Trace (儀器化)

    • 原理:Profiler 會在每一個函式的入口和出口都插入一個「探針」,精確記錄每個函式的開始時間和結束時間。

    • 優點:數據極其精確,不會錯過任何一個函式的調用。

    • 缺點:性能開銷巨大!它會嚴重拖慢你的 App,因此記錄到的時間數據可能會失真。

    • 適用場景:當你已經透過「採樣」大致定位到問題區域,需要對某個特定、複雜的函式進行微觀分析時使用。

作戰原則:永遠先用 Sampled (採樣) 進行大範圍偵查,鎖定嫌疑區域後,再考慮是否需要用 Trace (儀器化) 進行精準打擊。

第一次實戰:活捉一個卡頓元兇

現在,讓我們透過一個簡單的例子來演練一遍流程。假設我們的 App 中有以下一段「問題程式碼」,它會在主執行緒進行一個非常耗時的計算:

// 在你的 Activity 或 ViewModel 中
fun onButtonClick() {
// 模擬一個非常耗時的 CPU 密集型任務
// 注意:這是一個糟糕的範例,永遠不要在主執行緒做這種事!
var result = 0.0
for (i in 1..100_000_000) {
result += Math.sqrt(i.toDouble())
}
Log.d("Performance", "Calculation finished: $result")
}

當使用者點擊按鈕時,UI 會明顯凍結幾秒鐘。現在,我們的任務就是抓住 onButtonClick 這個元兇。

作戰步驟:

  1. 在 Profiler 的 CPU 視窗中,從下拉選單選擇 Java/Kotlin Method Sample

  2. 點擊 Record 按鈕,開始記錄。

  3. 在你的 App 中,點擊那個會觸發卡頓的按鈕

  4. 等待卡頓結束後,點擊 Stop 按鈕。

分析戰果:

記錄停止後,Profiler 會為你呈現一段時間內的 CPU 活動。你會看到一條長長的紅色或黃色條塊,這就是我們剛剛觸發的耗時操作。

在下方的分析面板中,選擇 Top Down 標籤頁。這個視圖會將耗時最長的函式路徑由上至下排列。

  • Total:該函式(包含其呼叫的所有子函式)總共佔用的時間。

  • Self:僅該函式自身執行的時間(不包含子函式)。

  • Children:其呼叫的子函式所佔用的時間。

在列表中,你應該能很快定位到 onButtonClick 這個函式,並看到它的 TotalSelf 時間都非常長。兇手找到了!

今日總結

恭喜你,完成了第一次成功的偵查任務!今天,我們學會了:

  • 如何啟動 CPU Profiler。

  • 區分並選擇 SampledInstrumented 兩種記錄模式。

  • 完成了一次完整的 記錄 -> 操作 -> 停止 -> 分析 流程,並成功捕獲了一個在主執行緒搞破壞的耗時函式。

然而,今天的範例還很簡單。在真實的戰場上,敵人會隱藏在更深的呼叫層級中。明天,我們將深入學習如何解讀更強大的視覺化工具——火焰圖 (Flame Charts),它能幫助我們在複雜的戰況中快速定位敵軍主力。

準備好迎接挑戰,我們明天見!


上一篇
# Day 1:【戰前宣言】為何性能優化是一場必須打贏的戰爭?
下一篇
# Day 3:【CPU Profiler】火焰圖 (Flame Charts) 完全解析
系列文
Android 性能戰爭:從 Profiler 開始的 30 天優化實錄3
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言