了解和排查 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、charge 和使用 memory.reclaim 的主动回收。
  13. kswapd 和 lmkd 交互:了解 kswapd 和 lmkd 在压力下如何协同工作。
  14. 将内存页返回给操作系统:使用 madvise 和 posix_fadvise 将未使用的堆页和文件缓存页返回给内核。

前提条件和环境

本指南提供了参考工作流、基准数据和案例研究,演示了如何诊断和解决 Android 内存问题。

  • 分析工具:本指南中的方法主要使用标准 Android 性能工具,包括 Perfetto、dumpsys meminfo、showmap 和 AHAT。
  • Root 权限:某些系统级诊断工作流(例如检查内核内存压力或硬件 PMU 计数器)需要在 userdebug 设备或模拟器 build 上具有提升的 root 权限 (adb root)。

起点:基本概念