操作說明

深入瞭解效能注意事項

8 分鐘閱讀

請先平復心情,讓我們進一步說明成效背景資訊。

歡迎來到「成效焦點週」第 3 天。今天,我們將繼續分享應用程式效能重要領域的詳細資料和指引。我們將介紹設定檔導引最佳化、Jetpack Compose 效能改善,以及幕後作業的注意事項。馬上開始吧!

設定檔指引最佳化

基準設定檔啟動設定檔是改善 Android 應用程式啟動和執行階段效能的基礎。這類最佳化屬於特性指引最佳化 (Profile Guided Optimization) 的一環。

封裝應用程式時,d8 dexer 會取得類別和方法,並填入應用程式的 classes.dex 檔案。使用者開啟應用程式時,系統會依序載入這些 DEX 檔案,直到應用程式可以啟動為止。提供「啟動設定檔」可讓 d8 瞭解要在第一個 classes.dex 檔案中封裝哪些類別和方法。這種結構可讓應用程式載入較少的檔案,進而提升啟動速度。

基準設定檔可有效將即時 (JIT) 編譯步驟從使用者裝置移至開發人員電腦。生成的預先 (AOT) 編譯程式碼已證實可縮短啟動時間,並減少算繪問題。

Trello 和基準設定檔

我們詢問 Trello 應用程式的工程師,基準設定檔對應用程式效能有何影響。將基準設定檔套用至主要使用者歷程後,Trello 發現應用程式啟動時間大幅減少 25%。

image.png

Trello 運用基準設定檔,將應用程式啟動時間縮短了 25%。

Meta 的基準設定檔

此外,Meta 的工程師最近也發布了一篇文章,說明他們如何運用基準設定檔加速 Android 應用程式

image.png

在套用基準設定檔後,Meta 應用程式的各項重要指標最多提升了 40%。

這類技術改良措施也有助於提升使用者滿意度和業務成效。與產品負責人、技術長和決策者分享這項資訊,也有助於提升應用程式效能。

開始使用基準設定檔

如要產生基準或啟動設定檔,請編寫會執行應用程式的 macrobenchmark 測試。測試期間會收集設定檔資料,供應用程式編譯時使用。這些測試是使用新的 UiAutomator API 編寫,我們會在明天介紹這個 API。

編寫這類基準測試很簡單,您可以在 GitHub 上查看完整範例。

  @Test

fun profileGenerator() {

    rule.collect(

        packageName = TARGET_PACKAGE,

        maxIterations = 15,

        stableIterations = 3,

        includeInStartupProfile = true

    ) {

        uiAutomator {

            startApp(TARGET_PACKAGE)

        }

    }


}

注意事項

首先,請為使用者最常使用的路徑編寫巨觀基準測試基準設定檔和啟動設定檔。也就是說,使用者進入應用程式的主要入口點,通常是登入後。然後繼續編寫更多測試案例,只針對基準設定檔擷取更完整的圖片。您不需要使用基準設定檔涵蓋所有內容。請使用最常用的路徑,並評估現場成效。我們會在明天的貼文中詳細說明。

開始使用設定檔引導最佳化功能

如要瞭解基準設定檔的運作方式,請觀看 Android 開發人員高峰會的這部影片:

如要進一步瞭解,請觀看 Android Build Time 的「Profile Guided Optimization」集:

我們也提供基準設定檔啟動設定檔的詳細指南,供您進一步瞭解。

Jetpack Compose 效能提升

Android 的 UI 架構效能投資已見成效。在內部長時間捲動基準測試中,Jetpack Compose 1.9 版的捲動卡頓率已降至 0.2%。

jankyFrames.png

這些改善項目得益於最新版本中內建的幾項功能。

可自訂的快取視窗

根據預設,延遲版面配置只會提前在捲動方向組合一個項目,且項目捲動離開畫面後就會遭到捨棄。您現在可以透過可視區域或 dp 大小的比例,自訂要保留的項目數量。這有助於應用程式預先執行更多工作,並在影格之間啟用可暫停的組合後,更有效率地運用可用時間。

如要開始使用可自訂的快取視窗,請例項化 LazyLayoutCacheWindow,並傳遞至延遲清單或延遲格線。使用不同的快取視窗大小 (例如可視區域的 50%) 評估應用程式的效能。最佳值取決於內容結構和項目大小。

  val dpCacheWindow = LazyLayoutCacheWindow(ahead = 150.dp, behind = 100.dp)

val state = rememberLazyListState(cacheWindow = dpCacheWindow)

LazyColumn(state = state) {

    // column contents

}

可暫停的組合

這項功能可暫停合成作業,並將工作分散到多個影格。這些 API 已在 1.9 版中推出,並在 1.10 版中預設用於延遲版面配置預先擷取。對於組合時間較長的複雜項目,您應該會看到最明顯的效益。

image.png

更多 Compose 效能最佳化

在 Compose 1.9 和 1.10 版中,團隊也進行了幾項較不明顯的最佳化。

我們改良了多個在背景使用協同程式的 API,舉例來說,使用 DraggableClickable 時,開發人員應會發現反應時間變快,且分配次數有所提升。

版面配置矩形追蹤的最佳化作業已提升修飾符 (例如 onVisibilityChanged()onLayoutRectChanged()) 的效能。即使未明確使用這些 API,也能加快版面配置階段的速度。

此外,透過 onPlaced() 觀察位置時,使用快取值也能提升效能。

在背景預先擷取文字

從 1.9 版開始,Compose 可以在背景執行緒上預先擷取文字。這樣一來,您就能預先暖機快取,加快文字版面配置速度,這與應用程式的算繪效能息息相關。在版面配置期間,文字必須傳遞至 Android 架構,系統會在此填入字詞快取。根據預設,這會在 UI 執行緒上執行。將預先擷取和填入字詞快取的工作卸載到背景執行緒,可以加快版面配置速度,尤其是較長的文字。如要在背景執行緒上預先擷取,您可以將自訂執行器傳遞至任何使用 BasicText 的可組合項,方法是將 LocalBackgroundTextMeasurementExecutor 傳遞至 CompositionLocalProvider,如下所示。

  val defaultTextMeasurementExecutor = Executors.newSingleThreadExecutor()

CompositionLocalProvider(

    LocalBackgroundTextMeasurementExecutor provides DefaultTextMeasurementExecutor

) {

    BasicText("Some text that should be measured on a background thread!")


}

視文字而定,這項功能可提升文字的顯示效能。為確保這項功能可提升應用程式的轉譯效能,請進行基準化並比較結果。

背景工作效能注意事項

對許多應用程式來說,背景工作是不可或缺的一環。您可能使用 WorkManager 或 JobScheduler 等程式庫執行下列工作:

  • 定期上傳分析事件
  • 在後端服務和資料庫之間同步處理資料
  • 處理媒體 (即調整大小或壓縮圖片)

執行這些工作時,主要挑戰在於兼顧效能和能源效率。WorkManager 可協助您取得這種平衡。這項功能的設計宗旨是節省電力,並允許將工作延後至最佳執行時間範圍,而這類時間範圍會受到多項因素影響,包括您指定的限制或系統強制執行的限制。

不過,WorkManager 並非一體適用的解決方案。Android 也提供多種經過電力最佳化的 API,專為特定常見的核心使用者歷程 (CUJ) 設計。  

如要查看其中幾項作業的清單,包括更新小工具和在背景取得位置資訊,請參閱「背景工作」到達網頁。

背景工作本機偵錯工具:常見情境

如要偵錯背景工作,並瞭解工作延遲或失敗的原因,您需要瞭解系統排定工作的方式。

為此,WorkManager 提供多項相關 工具,可協助您在本機進行偵錯及提升效能 (其中部分工具也適用於 JobScheduler)!以下列出使用 WorkManager 時可能遇到的常見情況,並說明可用於偵錯的工具。

偵錯排定工作未執行的原因

排定工作延遲或完全未執行,可能是因為多種因素,包括未符合指定限制,或系統強制設定限制

如要調查排定的工作未執行的原因,第一步是確認工作已成功排定。確認排程狀態後,請判斷是否有任何未達成的限制或先決條件,導致工作無法執行。

有多種工具可用於偵錯這個情境。

背景工作檢查器

背景工作檢查器是直接整合到 Android Studio 的強大工具。這個工具會以視覺化方式呈現所有 WorkManager 工作及其相關聯的狀態 (執行中、已加入佇列、失敗、成功)。

如要使用背景工作檢查器偵錯排定工作未執行的原因,請參閱列出的工作狀態。「已加入佇列」狀態表示工作已排定時間,但仍在等待執行。

優點:除了方便查看所有工作,這個工具在您有連鎖工作時特別實用。背景工作檢查器提供圖表檢視模式,可顯示先前的工作失敗是否影響後續工作執行。

image.png

背景工作檢查器清單檢視畫面

image.png

背景工作檢查器圖表檢視畫面

adb shell dumpsys jobscheduler

這項指令會傳回所有有效 JobScheduler 工作 (包括 WorkManager Worker) 的清單,以及指定限制和系統強制執行的限制。並傳回工作記錄。

如要以不同方式查看排定的工作和相關限制,請使用這個檢視畫面。如果是 WorkManager 2.10.0 之前的版本,adb shell dumpsys jobscheduler 會傳回具有這個名稱的工作站清單:

  [package name]/androidx.work.impl.background.systemjob.SystemJobService

如果應用程式有多個工作站,更新至 WorkManager 2.10.0 後,您就能查看工作站名稱,輕鬆區分不同工作站:

  #WorkerName#@[package name]/androidx.work.impl.background.systemjob.SystemJobService

優點: 這項指令有助於瞭解是否有任何系統強制執行的限制 ,而您無法透過背景工作檢查器判斷。舉例來說,這會傳回應用程式的待機值區,進而影響排定工作完成的時段。

啟用偵錯記錄功能

您可以啟用自訂記錄,查看詳細的 WorkManager 記錄,其中會附加 WM—

優點:您可以掌握工作排程、限制條件是否符合,以及生命週期事件,並在開發應用程式時參考這些記錄。

WorkInfo.StopReason

如果發現特定工作站的效能難以預測,可以透過程式輔助方式,使用 WorkInfo.getStopReason 觀察工作站在上一次執行嘗試中停止的原因。 

建議您設定應用程式,使用 getWorkInfoByIdFlow 觀察 WorkInfo,判斷工作是否受到背景限制、限制、頻繁逾時的影響,甚至是遭到使用者停止。

福利:您可以使用 WorkInfo.StopReason 收集有關 worker 績效的現場資料。

對 Android Vitals 標記的 WorkManager 造成高 Wake Lock 時間進行偵錯

Android Vitals 提供「部分 Wake Lock 使用過度」指標,可突顯導致電池耗電的 Wake Lock。您可能不知道 WorkManager 會取得喚醒鎖定來執行工作,如果喚醒鎖定超出 Google Play 設定的門檻,可能會影響應用程式的曝光度。如何偵錯,瞭解為何工作會導致這麼長的 Wake Lock 時間?您可以使用下列工具。

Android Vitals 資訊主頁

首先,請在 Android Vitals 喚醒鎖定時間過長資訊主頁中確認,喚醒鎖定時間過長來自 WorkManager,而非鬧鐘或其他 Wake Lock。您可以參閱「識別其他 API 建立的喚醒鎖定」說明文件,瞭解哪些喚醒鎖定是由於 WorkManager 而保留。

Perfetto

Perfetto 是一款用於分析系統追蹤記錄的工具。如果專門用於偵錯 WorkManager,您可以查看「裝置狀態」部分,瞭解工作開始時間、執行時間,以及對耗電量的影響。

在「裝置狀態:工作」軌跡下方,您可以查看已執行的任何工作者及其相關聯的喚醒鎖定。

deviceState.png

Perfetto 中的「裝置狀態」部分,顯示 CleanupWorker 和 BlurWorker 的執行情況。

資源

如要瞭解其他情境適用的偵錯方法,請參閱「Debug WorkManager page」(偵錯 WorkManager 頁面) 的總覽。

如要實際操作這些方法,並進一步瞭解如何偵錯 WorkManager,請參閱「 進階 WorkManager 和測試」程式碼研究室。

後續步驟

今天我們不只介紹程式碼縮減功能,還探討了 Android 執行階段和 Jetpack Compose 實際算繪應用程式的方式。無論是使用基準設定檔預先編譯重要路徑,還是透過新的 Compose 1.9 和 1.10 功能順暢捲動狀態,這些工具的重點都是提升應用程式的使用體驗。此外,我們也深入探討了偵錯背景作業的最佳做法。

Ask Android

我們將於週五舉辦成效問答活動。現在就使用 #AskAndroid 提問,讓專家為你解答。

挑戰

我們在週一向您發出挑戰,請您啟用 R8。我們今天請您為應用程式產生一個基準設定檔

使用 Android Studio Otter,您就能透過基準設定檔產生器模組精靈,輕鬆完成這項作業。選擇最重要的關鍵使用者歷程 (即使只是應用程式啟動和登入),然後產生設定檔。

取得後,請執行 Macrobenchmark,比較 CompilationMode.NoneCompilationMode.Partial

在社群媒體上分享啟動時間的改善成果,並加上 #optimizationEnabled 主題標記。

敬請期待明天的內容

您已使用 R8 縮減應用程式,並透過設定檔指引最佳化功能,最佳化執行階段。但要如何向利害關係人證明這些成效?您又該如何找出回歸問題,避免影響正式版?

歡迎明天參加第 4 天:效能調平指南,我們將詳細說明如何衡量成效,包括 Play Vitals 中的實際資料,以及使用 Perfetto 進行深入的本機追蹤。

繼續閱讀