内存用量(匿名 RSS + 交换空间)是 Android Vitals 中的一项指标,反映了应用的内存用量。
匿名内存是指没有存储器中的文件支持的内存,例如 堆分配和 mmap 分配的内存。此指标会捕获应用的动态内存分配,包括 Java 或 Kotlin 堆、非托管原生堆分配(其中位图像素数据位于 Android 8.0(API 级别 26)及更高版本)和线程执行堆栈。虽然操作系统可以在压力下丢弃文件支持的内存,但无法丢弃匿名内存。
常驻内存大小 (RSS) 是指进程使用的内存页(共享 和非共享)总数,这些内存页保存在物理 RAM 中。如果某个页面被多个进程(例如访问同一库的应用)访问,则该页面被视为“共享”页面。
对于匿名内存,当内存压力过大时,系统可以将页面写入 交换空间(或 Android 上的 zRAM)。 如果需要,系统可以从交换空间中读回这些页面。
总而言之,内存用量(匿名 RSS + 交换空间)衡量的是应用中没有存储器中的文件支持的内存页总数,包括系统在交换空间中保留的任何内存。跟踪匿名 RSS + 交换空间可确保您看到应用真实的、无法被逐出的内存占用情况。
如果应用的内存用量较高,请进一步调查并使用本页上的指南解决问题。
识别高内存用量
Android Vitals
Android Vitals 会按以下 进程状态细分应用的内存用量:
- 前台:应用的进程可见。此处的 P99 值较高通常会影响用户感知到的性能(卡顿或 OOM 崩溃),并且很大程度上是由未被逐出的界面组件或 activity 导致的。
- 前台服务:应用正在运行前台服务。由于这些服务是为长时间运行的任务而设计的,因此它们是累积生命周期泄漏的主要候选对象,这些泄漏会随着时间的推移而大幅增加 P99 尾部。
- 后台:应用正在运行后台服务,或最近已转到 后台,但尚未缓存。这是后台处理泄漏复合的地方。
- 已缓存:应用处于缓存状态。此状态对系统内存压力(例如 LMK)高度敏感。由于操作系统可以随意逐出此进程状态,因此仅出于调试目的提供此状态。
如需了解这些进程状态与 onTrimMemory 回调之间的关联,
请参阅有关响应事件时释放内存的指南。
Android Vitals 还会按 RAM 存储分区细分应用的内存用量。 内存用量指标以每日百分位数值的时间轴形式显示,同时显示第 50 个和第 90 个百分位的最新每日值。
使用尾部偏斜识别内存泄漏
为了帮助识别内存泄漏,请在 Android Vitals 中查找典型 (P50) 用户与尾部 (P90) 用户之间的差异。虽然一般资源膨胀会使所有百分位的内存均匀增加,但内存泄漏会随着时间的推移而复合,从而严重偏斜尾部数据。
您应按进程名称将 P90 和 P99 指标与 P50 基准进行比较。如果 P90 与 P50 的比率超过 3.5 倍,则表示在长时间会话期间可能发生内存泄漏。对于某些用例,比率升高并不总是表示泄漏,但您应评估具体的工作流,以确定内存用量升高是否为预期行为。
资源
在本地诊断过高的内存用量
如需开始诊断过高的内存用量的来源,您可以 使用开发者设置、Android Studio或Perfetto中的记录堆转储捕获堆转储。我们建议您先在测试应用的核心用户历程后,在本地捕获堆转储。
我们尤其建议您测试以下用户历程:
- WebView 和应用内浏览器会话
- 媒体内容较多的无限滚动
- 素材资源创建和修改流程
如需调查潜在的内存泄漏,请先使用 Android Vitals 内存用量信息中心内的进程名称 表格识别用量最高的进程。接下来,在本地运行相应的用户历程,并在不同的进程状态(可见、前台服务和缓存)下收集堆转储,以验证应用在转到后台后是否会释放内存。
如果您使用 Android Studio 性能分析器调试内存问题,还可以使用 LeakCanary 集成来简化泄漏检测,并使用重复位图检测来优化图片用量。
收集堆转储后,我们建议您使用 Perfetto AI Skills 分析堆转储,并识别高内存用量的潜在来源 。
以下是 AI Skills 可能响应的示例:
I have completed the analysis of memory leaks and bitmap issues for [app] using the provided Perfetto trace.
Summary of Findings
The investigation identified a critical memory pressure issue caused by massive bitmap retention within the app process.
...
Recommendations for [app]
1. [Library] Image Cache Optimization:
* Review the [Library] caching strategy. Ensure that bitmaps
loaded for animations are released or downsampled when the animation is
not in the foreground.
2. Asset Resolution Audit:
* The 14.7 MB average size suggests full-screen or extremely high-density assets. Audit the [library] files in the native_home component to ensure they are not using unnecessarily large source images.
3. View Lifecycle Management:
* Investigate why 21 [LibraryImage] instances are alive simultaneously. Ensure that views in the bottom
tab are properly detached or their animations are cleared when switching between tabs.
4. Fix Surface Leaks:
* Address the Surface.release failures observed in the logs, as these can lead to both memory leaks and
native resource exhaustion.
用于解读堆转储的其他资源
以下资源提供了有关解读堆转储和调试内存用量的更多信息:
- 手动分析:使用Perfetto 堆转储浏览器指南,了解如何在 Perfetto 界面中浏览和解读堆转储可视化内容。
- Java/Kotlin 分配:阅读可视化您的第一个 ART 堆转储,了解分析 Android 运行时 (ART) 堆转储的分步指南。
- 原生分配:请参阅Perfetto 原生性能分析文档,了解如何收集和分析原生 (C/C++) 内存配置文件。
- CLI 检查: 使用 adb dumpsys meminfo 快速了解应用在设备上的内存用量细分情况。
- AI 辅助分析:利用 Perfetto AI Skills 运行依托 LLM 的分析,帮助检测跟踪记录中的内存泄漏和过多的分配。
- 基于 SQL 的分析:使用 Perfetto SQL 和跟踪分析 Skills 运行结构化查询和专用脚本,以分析复杂的跟踪数据。
提高内存用量
请参阅以下部分,详细了解如何提高应用的内存用量:
如需有关解决内存问题的详细指南,请参阅管理应用的 内存指南。