瞭解及排解 Android 記憶體問題

記憶體是 Android 裝置上重要且有限的資源。身為 Android 平台開發人員或原始設備製造商 (OEM),您必須瞭解記憶體在各個層級 (從 Java 執行階段到 Linux 核心) 的運作方式,才能建構高效能且穩定的系統。

本指南將全面介紹 Android 記憶體架構、可用的分析工具,以及實用練習,協助您找出並解決記憶體相關問題。

目標

完成本指南後,您將能夠:

  • 說明 Android 記憶體的基本概念,包括 Zygote 程序模型和記憶體對應檔案。
  • 區分常設集大小 (RSS)、比例集大小 (PSS) 和不重複集大小 (USS)。
  • 使用 dumpsys meminfo 和 showmap 等標準指令列工具,快速評估記憶體用量。
  • 使用 AHAT 擷取及分析 Java 記憶體快照資料,找出流失和過度分配問題。
  • 使用 Perfetto 和 heapprofd,剖析整個系統的 Java 和原生記憶體。
  • 瞭解系統層級的記憶體壓力指標,例如壓力停滯資訊 (PSI),並監控記憶體不足終止工具 (LMK) 活動。
  • 觀察核心層級的回收活動,包括 ZRAM 交換和頁面快取清除。

指南結構

本指南分為以下幾個部分,建議依序閱讀:

  1. 基本概念:Android 記憶體的核心技術原則。
  2. 快速評估工具:使用 meminfo、showmap 和 procstats 快速分類。
  3. 分析 Java 記憶體:使用 AHAT 深入分析 Java 堆積。
  4. 點陣圖和記憶體:瞭解圖片對 RAM 的影響,並使用工具進行分析。
  5. 分析原生記憶體:使用 Perfetto 和 heapprofd 分析 C/C++ 記憶體。
  6. WebView 和記憶體:瞭解 WebView 的多程序架構和記憶體用量。
  7. 應用程式程式碼是記憶體:瞭解類別載入和 dex 膨脹對 RAM 的影響。
  8. 執行緒和記憶體:分析原生執行緒堆疊的成本。
  9. 記憶體位置和效能:瞭解資料存取模式如何影響 CPU 效能。
  10. 服務繫結和程序狀態:瞭解跨程序依附元件如何影響 OOM 分數。
  11. 系統層級疑難排解:監控 PSI、LMK、ZRAM 交換和頁面快取清除。
  12. 記憶體回收:剔除和交換:瞭解 memcg、計費和主動回收,以及 memory.reclaim。
  13. kswapd 和 lmkd 互動:瞭解 kswapd 和 lmkd 在壓力下如何協同運作。
  14. 將記憶體頁面傳回 OS:使用 madvise 和 posix_fadvise 將未使用的堆積頁面和檔案快取頁面傳回核心。
  15. 使用精簡程序維持背景工作:將背景服務和工作站移至專屬程序,避免 UI 和圖形記憶體維持較高優先順序。

事前準備和環境

本指南提供參考工作流程、基準資料和個案研究,說明如何診斷及解決 Android 記憶體問題。

  • 分析工具:本指南中的技術主要使用標準 Android 效能工具,包括 Perfetto、dumpsys meminfo、showmap 和 AHAT。
  • Root 權限:部分系統層級診斷工作流程 (例如檢查核心記憶體壓力或硬體 PMU 計數器),需要使用者偵錯裝置或模擬器建構作業的提升 Root 權限 (adb root)。

從這裡開始:基本概念