個案研究

Grab 運用 R8 和設定檔引導最佳化功能,將 ANR 發生率降低 32%,並將啟動時間縮短 35%

閱讀時間:5 分鐘

Grab 是東南亞首屈一指的超級應用程式,透過單一應用程式為八個國家/地區的數百萬名使用者提供外送、交通和金融服務。Grab 團隊擁有 10 年歷史的程式碼集,其中包含超過 1,000 萬行程式碼,以及數百個使用 Bazel 和 Gradle 混合設定建構的第三方資料庫,因此面臨三個日益嚴峻的挑戰:應用程式無回應 (ANR) 發生率偏高、超級應用程式新增服務導致應用程式大小持續增加,以及啟動時間逐年緩慢增加。Grab 啟用 R8 最佳化功能、調整保留規則,並導入基準設定檔和啟動設定檔,成功將使用者感知 ANR 事件的發生率降低 32%、應用程式下載大小減少約 30%,啟動時間也縮短 35%。

消除發布後 ANR 激增問題,提供更流暢的使用者體驗

在最佳化建構程序之前,Grab 每次推出新版本後,都會立即面臨冷啟動延遲和應用程式無回應 (ANR) 錯誤激增的問題,主要原因是應用程式初始化期間讀取大量 DEX 檔案,導致負擔過重。

雖然 Google Play 的雲端設定檔可為整體使用者族群的最佳化標準流程,但無法最佳化 Grab 關鍵使用者歷程所需的所有初始化路徑,例如在應用程式啟動期間初始化 Dagger 依附元件圖。對於初始發行版本未涵蓋的程式碼路徑,裝置在後續幾天會依賴 JIT 編譯和本機背景最佳化。導入自訂 基準設定檔後,這些關鍵使用者歷程會直接提供給 Google Play 的雲端設定檔,擴大最佳化範圍,讓這些重要路徑在安裝時立即編譯成機器碼,進而解決這個問題。

ANDDM_Grab_Inline_Quote_ALT.png

Grab 乘客應用程式核心團隊的首席軟體工程師 Nguyen Van Minh 表示:「我們每週發布應用程式時,ANR 發生率都會飆升。」

為消除 ANR 並縮短啟動時間,Grab 實施了 R8 最佳化、基準設定檔和啟動設定檔。設定檔導引最佳化和 R8 最佳化工具,讓冷啟動時間立即縮短 12%,基準設定檔則進一步縮短 15%,啟動時間共縮短 27%,並有效消除發布後 ANR 錯誤激增的問題。

Grab 透過三個策略階段執行這項應用程式最佳化作業:在相容模式下啟用 R8 最佳化、轉換至 R8 完整模式,然後使用設定分析器調整保留規則,並新增 CI/CD 治理。

第 1 階段:啟用 R8 最佳化  (2025 年推出)

在第一階段,Grab 捨棄舊版預設 Proguard 檔案,改用 proguard-android-optimize.txt,啟用 R8 最佳化功能。由於程式碼集已有十多年歷史,且包含超過 1, 000 萬行程式碼,因此必須先處理舊版設定和反射用法,才能啟用最佳化工具。

為了盡可能提高這個階段的成效,Grab 發布了啟用 R8 相容模式的應用程式更新,並加入基準設定檔和啟動設定檔。這些措施立竿見影,使用者感知 ANR 發生率立即降低 25%,應用程式下載大小減少 16%,冷啟動時間整體縮短 27%。

第 2 階段:R8 完整模式和遷移 (2026 年推出)

在首次推出九個月後,這個階段將應用程式切換至 R8 完整模式,進一步提升最佳化效果。Retrofit、Firebase 和 Jetpack Compose 等標準程式庫,可使用內建規則與 R8 完美搭配運作,但其餘龐大的程式碼集則需要解決特定反射密集型程式碼路徑,才能完成遷移:

為了遷移至 R8 完整模式,團隊採用了最新 Gson 版本中的消費者保留規則,確保 JSON 剖析作業順暢進行。他們也解決了 Java 動態 Proxy 的最佳化難題,這類 Proxy 會使用反射機制,在執行階段產生介面實作。由於 R8 無法在編譯期間偵測到這項執行階段用量,因此會移除或重新命名必要類別,導致應用程式當機。該團隊並未套用廣泛的例外狀況,以免應用程式大小膨脹,而是找出依賴反射的特定類別,並實施高度精確的保留規則,同時兼顧應用程式穩定性和最佳化效率。

最終,R8 完整模式帶來了巨大的複合式改善,包括應用程式下載大小額外減少 14%、啟動時間額外縮短 10%,以及使用者感知 ANR 事件次數再減少 10%。遷移至 R8 完整模式後,Grab 的程式碼集達到以下 R8 最佳化分數。

  • 最佳化分數:72%
  • 縮減分數:73%
  • 模糊化分數:79.6%

這些分數可提供 R8 設定的意見回饋,以及是否需要調整保留規則,盡可能提高 R8 最佳化成效。

第 3 階段:調整保留規則 

在最佳化旅程的最後階段,Grab 著重於建立長期程式碼集健康狀態、持續監控效能,以及嚴格控管編譯作業。為了系統化評估規則整潔度,並防止在持續發布週期中發生設定迴歸,團隊將 R8 設定分析器整合至評估工作流程。這項工具可深入瞭解 Grab 的保留規則如何讓 R8 最佳化、縮減及模糊處理應用程式。

Grab 以 R8 完整模式為基礎,有條不紊地刪減舊版保留規則,在分析工具評估的三個核心面向,都取得大幅改善:

  • 最佳化分數:從 72% 提高至 78.2%
  • 縮減分數:從 73% 提高至 79.1%
  • 模糊化分數:從 79.6% 提高到 81.7%

除了提升這些診斷分數外,這個專門的保留規則精細調整階段,還能將應用程式下載大小額外縮減約 3.6%。更重要的是,追蹤這些指標可為工程團隊提供客觀資料,用於實施自動化預先合併 CI 防護措施,確保新引入的程式碼符合嚴格的保留規則標準,並長期維持得來不易的效能提升。

結果

R8 最佳化工具推出後,效能有以下重大改善:

最佳化階段ANR大小冷啟動
第 1 階段:R8 最佳化工具 (2025 年推出)減少約 25%減少 16%改善約 27%
第 2 階段:R8 完整模式 (2026 年推出)減少 10%減少 14%10%
保留規則最佳化-減少 3.6%-
整體 (累計)減少約 32.5%減少約 30.4%提升約 35%

技術挑戰 

在 Grab 累積十年的程式碼集中啟用 R8 最佳化工具,會帶來大規模的重要技術障礙:

  • 測試:經過十年的反思,我們在全面最佳化後發現了極端案例。由於無法對數百萬行程式碼進行全面測試,團隊採取了漸進式、高優先順序的方法,特別針對縮小保留規則涵蓋的程式碼進行測試,並反覆調整這些規則,只針對反射所需的特定類別、方法或欄位,以最大化 R8 最佳化。
  • 建構延遲時間和混合架構:Grab 的混合建構系統 (Bazel 用於偵錯,Gradle 用於 R8 發布子版本) 意味著實驗性 R8 變更在遠端 CI 中最多需要 2 小時。為縮短意見回饋時間,Grab 調整每日品質確保建構作業,使其與正式版 R8 行為一致,並自動收集 mapping.txt、configuration.txt 等重要 CI 建構構件,簡化調查程序。
  • 偵錯週期緩慢:在數百個最佳化類別中追蹤根本原因,對精實團隊造成沉重負擔。Grab 透過 Gradle 自動將對應檔案上傳至 Firebase Crashlytics,並為 Play 管理中心繫結去模糊化對應,解決了這個問題,讓執行階段問題能立即準確解析符號

R8 對程式碼的長期影響

除了立即提升效能外,啟用 R8 最佳化工具也為 Grab 的龐大程式碼集帶來永久的結構優勢。Grab 團隊使用開放原始碼工具 app-sizer 評估 R8 的影響,發現 R8 永久降低了應用程式中每行程式碼的下載大小。

ANDDM_Grab_Inline_Metric.png

在 AI 輔助開發時代,程式碼數量迅速增加,因此這項最佳化作業更顯重要。如果不使用 R8,程式碼擴充會按比例增加下載大小。R8 可確保程式碼擴充率相同,同時大幅減少記憶體用量。

注意:方法:app-sizer 的 Kotlin/Java 對應用程式下載大小 (代表性裝置) 的貢獻,除以實際工作環境 Kotlin LOC (cloc;僅限主要來源集;不含測試、模擬和範例模組)。

Keep 規則管理和護欄

為避免規則退化,並長期維持 R8 最佳化,Grab 計劃將自動化預先合併防護措施直接整合至 CI 管道。根據這項政策,新的保留規則受到嚴格限制,任何額外規則都必須提供明確理由並經過審查。Grab 團隊在 CI 中追蹤 R8 最佳化分數。在此基礎上,團隊計劃將這些指標做為持續回饋循環,在合併前找出迴歸問題,並在每個發布週期中保留最佳化成果。

R8-rules-score (1).png

圖 1:CI 資訊主頁追蹤 Grab 建構作業的 R8 縮減、最佳化和模糊化分數,主動找出並防止各版本發生迴歸。

結論 

Grab 的 Pax App Core 團隊面臨龐大且成熟的程式碼集挑戰,因此主動導入基準設定檔,並持續改善 R8 設定,解決啟動時間增加和發布後效能不穩定的問題。團隊將使用者感知 ANR 事件減少約 32.5%、應用程式下載大小縮減約 30.3%,冷啟動時間縮短約 35%,同時從根本上提升程式碼集擴充效率。

這些最佳化措施為東南亞數百萬名使用者提供更快速、更穩定的超級應用程式體驗,同時讓 Grab 的工程師能更快速地建構功能,而不必擔心下載大小快速膨脹。

如要開始使用並進一步瞭解 R8,請前往 - d.android.com/r8。

繼續閱讀