應用程式啟動分析與最佳化

使用者會透過應用程式啟動期間的體驗,建立他們對應用程式的第一印象。應用程式啟動程序必須快速載入並顯示使用者使用應用程式所需的資訊。如果應用程式啟動時間過長,使用者可能會因為等候時間太長而退出應用程式。

我們使用 Macrobenchmark 程式庫來測量啟動時間。這個程式庫可提供總覽和詳細的系統追蹤記錄,方便您掌握啟動期間發生的確切情況。

系統追蹤記錄會提供有關裝置動態的實用資訊,讓您瞭解應用程式在啟動期間做了哪些事、有哪些潛在改進方向。

如要分析應用程式啟動情況,請執行下列操作:

分析及改進應用程式啟動程序的步驟

一般來說,應用程式需要在啟動時載入對使用者至關重要的資源。非必要的資源可以等到啟動程序完成後再載入。

如要權衡效能,建議您考慮以下幾點:

  • 使用 Macrobenchmark 程式庫評估各項作業的用時,找出需要較長時間才能完成的區塊。

  • 確認資源密集型作業對於應用程式啟動程序具有重要作用。如果該作業可以等到應用程式繪製完成再執行,即可將啟動時的資源限制降到最低。

  • 檢查該作業是否應在應用程式啟動時執行。舊程式碼或第三方程式庫常會呼叫不必要的作業。

  • 如果可行,請將長時間執行的作業移至背景。背景程序還是可能會影響啟動期間的 CPU 用量。

徹底調查作業後,就可以在所需載入時間與是否需要在應用程式啟動期間納入這項作業之間做出取捨。如要修改應用程式的工作流程,請留意會有發生迴歸或破壞性變更的風險。

反覆改進與評估,直到您對應用程式的啟動時間感到滿意為止。如需更多資訊,請參閱「使用指標偵測及診斷問題」。

測量及分析主要作業耗費的時間

取得完整的應用程式啟動追蹤記錄後,請查看這份記錄並評估 bindApplicationactivityStart 等主要作業耗費的時間。我們建議使用 PerfettoAndroid Studio 分析器 來分析這些追蹤記錄。

請查看應用程式啟動花費的總時間,看看是否有符合下述情形的作業:

  • 需要較長時間、具有改進空間。每一毫秒都對效能至關重要。比如,請留意 Choreographer 繪製時間、版面配置加載時間、程式庫載入時間、Binder 交易,或資源載入時間一般來說,請先檢查所有處理時間超過 20 毫秒的作業。
  • 封鎖主執行緒。詳情請參閱「瀏覽 Systrace 報表」。
  • 不需要在啟動期間執行。
  • 可以等第一個影格繪製後再執行。

請深入調查每筆追蹤記錄,找出效能有差距的地方。

找出主執行緒上昂貴的作業

最佳做法是將檔案 I/O 和網路存取等昂貴的作業從主執行緒移出。在應用程式啟動時,這一點也同樣重要,因為主執行緒上的作業費用十分昂貴,可能會導致應用程式無回應,並延遲其他重要作業。StrictMode.ThreadPolicy 可協助您找出主執行緒中發生昂貴作業的情況。建議您在偵錯版本上啟用 StrictMode,盡早發現問題,如以下範例所示:

Kotlin

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        ...
        if (BuildConfig.DEBUG)
            StrictMode.setThreadPolicy(
                StrictMode.ThreadPolicy.Builder()
                    .detectAll()
                    .penaltyDeath()
                    .build()
            )
        ...
    }
}

Java

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        ...
        if(BuildConfig.DEBUG) {
            StrictMode.setThreadPolicy(
                    new StrictMode.ThreadPolicy.Builder()
                            .detectAll()
                            .penaltyDeath()
                            .build()
            );
        }
        ...
    }
}

使用 StrictMode.ThreadPolicy 會在所有偵錯版本上啟用執行緒政策,只要偵測到違反執行緒政策的情形,應用程式就會當機,導致您難以錯過執行緒政策違規事件。

TTID 和 TTFD

如要查看應用程式產生第一個影格所需的時間,請評估初始顯示時間 (TTID)。不過,這項指標不一定會反映使用者能開始與應用程式互動前的等候時間。因此,如果您希望應用程式狀態完整可用,就更適合使用完整顯示時間 (TTFD) 指標評估及改善必要的程式碼路徑。

如要瞭解應用程式 UI 繪製完成後的回報策略,請參閱「提高啟動時間準確度」。

請同時針對 TTID 和 TTFD 進行最佳化,因為兩者在各自的領域都至關重要。TTID 偏短時,有助於使用者瞭解應用程式正在確實啟動;而維持偏短的 TTFD,則是確保使用者能快速與應用程式互動的關鍵。

分析整體執行緒狀態

選取應用程式啟動時間,查看整體執行緒配量。主要執行緒必須隨時能夠回應。

Android Studio ProfilerPerfetto 等工具會提供主執行緒的詳細總覽資訊,以及每個階段花費的時間。如要進一步瞭解如何以視覺化方式呈現 Perfetto 追蹤記錄,請參閱「Perfetto UI」說明文件。

找出主執行緒休眠狀態的關鍵區塊

如果應用程式長時間處於休眠狀態,可能是因為應用程式的主執行緒正在等待工作完成。對於多執行緒的應用程式,請找出主執行緒在等待的執行緒,並考慮改進相關作業。這也有助於確保關鍵路徑不會因為不必要的鎖定爭用而出現延遲。

減少讓主執行緒進入封鎖和不可中斷的休眠狀態

請找出每次主執行緒進入封鎖狀態的情況。Perfetto 和 Studio Profiler 的執行緒狀態時間軸會以橘色指標顯示這些情況。請辨識相關作業,檢查這些作業是否符合預期或可以避免,並視需要加以改進。

與 IO 相關的可中斷休眠可能是值得改進的地方。其他執行 IO 的程序 (甚至是無關的應用程式) 都能與頂端應用程式在執行的 IO 競爭。

縮短啟動時間

找出可以改進的空間後,請探索可能有助於縮短啟動時間的解決方案:

  • 延後並以非同步方式載入內容,縮短初始顯示時間
  • 盡量減少會做出繫結器呼叫的呼叫函式。如果這類函式具有必要性,請務必改進相關呼叫,比如以快取值的方式取代重複呼叫,或是將非封鎖性工作移至背景執行緒。
  • 為了讓應用程式看起來更快啟動,可以盡快對使用者顯示需要最少轉譯作業的內容,讓他們不必空等畫面其餘部分載入。
  • 在應用程式中建立及新增啟動設定檔
  • 使用 Jetpack 應用程式啟動程式庫,簡化應用程式啟動期間的元件初始化作業。

分析 UI 效能

應用程式啟動程序包括啟動畫面和首頁載入時間。如要改進應用程式啟動程序,請查看追蹤記錄,瞭解繪製 UI 所需的時間。

限制初始化作業

某些影格的載入時間可能比較久。這類影格可視為在應用程式中具有較高的繪製成本。

如要改善初始化作業,請執行下列操作:

  • 優先處理並改進緩慢的版面配置階段。
  • 新增自訂追蹤記錄事件,方便調查來自 Perfetto 的每個警告以及 Systrace 發出的所有快訊,減少高成本的繪圖和延遲情形。

測量影格資料

評估影格資料的方法有很多種,以下是五種主要的資料收集方法:

  • 使用 dumpsys gfxinfo 進行本機收集:在 dumpsys 資料中觀察到的影格不一定都會導致應用程式轉譯速度緩慢,或是對使用者造成任何影響。不過,觀察這項指標在不同發布週期之間的變化,有助於掌握整體的效能趨勢。想進一步瞭解如何使用 gfxinfoframestats 將 UI 效能測量結果整合至測試,請參閱「測試 Android 應用程式的基礎知識」。
  • 使用 JankStats 收集欄位資料:使用 JankStats 程式庫從應用程式的特定部分收集影格轉譯時間資料,並記錄及分析資料。
  • 在測試中使用 Macrobenchmark (後端有 Perfetto)
  • Perfetto FrameTimeline在 Android 12 (API 級別 31) 中,您可以從 Perfetto 追蹤記錄中收集影格時間表指標,瞭解導致影格遺失的工作。如果想診斷影格遺失的原因,不妨先從這裡著手。
  • 使用 Android Studio Profiler 偵測卡頓情形

查看主要活動載入時間

應用程式的主要活動可能包含從多個來源載入大量資訊。請檢查首頁的 Activity 版面配置,特別是查看首頁活動的 Choreographer.onDraw 方法。

  • 使用 reportFullyDrawn 向系統回報,應用程式繪製作業已完全符合最佳化要求。
  • 使用 StartupTimingMetric 搭配 Macrobenchmark 程式庫來評估活動和應用程式啟動情形。
  • 查看影格遺失情形。
  • 找出轉譯或測量很耗時的版面配置。
  • 找出載入很耗時的素材資源。
  • 找出不需要在啟動期間加載的版面配置。

如要縮短主要活動的載入時間,請考慮以下可行的解決方案:

  • 在初始版面配置上,盡可能只顯示基本元素。詳情請參閱「最佳化版面配置階層」。
  • 新增自訂追蹤點,取得有關影格遺失和複雜版面配置的更多資訊。
  • 盡量減少啟動期間載入的點陣圖數量與大小。
  • 在版面配置非立即 VISIBLE 的地方使用 ViewStubViewStub 是大小為零的隱藏檢視區塊,可用於在執行階段延後加載版面配置資源。詳情請參閱 ViewStub 的說明。

    使用 Jetpack Compose 時,您可以使用狀態延遲載入部分元件,執行與 ViewStub 類似的行為:

    var shouldLoad by remember {mutableStateOf(false)}
    
    if (shouldLoad) {
     MyComposable()
    }
    

    修改 shouldLoad,在條件式區塊中載入可組合函式:

    LaunchedEffect(Unit) {
     shouldLoad = true
    }
    

    這會觸發重組作業,將程式碼置於第一個程式碼片段的條件式區塊中。