内存管理-31-系统内存统计-6-dumpsys meminfo
注: 内存芯片通常以1024为进制单位,存储芯片通常以1000为进制单位。
一、dumpsys meminfo命令数据格式
基于Android-14(U)
# dumpsys meminfo Applications Memory Usage (in Kilobytes): Uptime: 2802229 Realtime: 2802229 Total RSS by process: 313,100K: com.sam.systemui (pid 1848 / activities) 169,676K: zygote64 (pid 789) 78,672K: surfaceflinger (pid 983) 23,076K: init (pid 1) 22,208K: android.hardware.audio.service.mediatek (pid 812) 9,972K: sh (pid 10262) ... Total RSS by OOM adjustment: 1,851,392K: Native 169,676K: zygote64 (pid 789) 21,144K: adbd (pid 10227) 6,744K: android.hardware.boot-service (pid 415) ... 478,508K: System 478,508K: system (pid 1116) //system_server 5,472,900K: Persistent 1,011,564K: com.sam.systemui (pid 2700) 135,884K: com.android.phone (pid 1853) ... 144,808K: Persistent Service 144,808K: com.android.providers.media.module (pid 2664) 926,208K: Foreground 184,780K: com.sam.car.settings (pid 1955 / activities) 158,308K: com.sam.caraccount (pid 4090) ... 2,230,584K: Visible 134,912K: com.sam.btphone (pid 5527) 111,776K: android.ext.services (pid 3481) (user 10) ... 2,248,828K: Perceptible 298,372K: com.sam.xpime (pid 6680) 109,052K: com.mediatek.location.mtkgeofence (pid 3072) ... 432,464K: B Services 150,188K: com.sam.cardiagnosis (pid 6306) 146,616K: com.sam.autoshow (pid 6268) 1,985,924K: Cached 142,932K: com.sam.appstore (pid 3227) 122,924K: com.android.rkpdapp (pid 4404) 121,332K: android.process.media (pid 10238) ... Total RSS by category: 3,211,292K: .so mmap 2,734,456K: Native 2,360,968K: .art mmap 2,219,852K: .jar mmap 1,278,964K: Dalvik 897,860K: .apk mmap 790,088K: Unknown 785,988K: .oat mmap 666,164K: GL mtrack 310,316K: Other mmap 190,000K: Dalvik Other 107,376K: .dex mmap 92,688K: Other dev 59,080K: Ashmem 54,824K: Stack 11,700K: .ttf mmap 0K: Cursor 0K: Gfx dev 0K: EGL mtrack 0K: Other mtrack Total PSS by process: 1,022,509K: com.sam.carspeech (pid 3186) 302,883K: system (pid 1116) //system_server 55,368K: surfaceflinger (pid 983) 16,719K: adbd (pid 10227) ... Total PSS by OOM adjustment: 1,722,628K: Native 165,303K: mtkfastavm (pid 2765) 86,557K: camerahalserver (pid 1208) 55,368K: surfaceflinger (pid 983) ... 302,883K: System 302,883K: system (pid 1116) //system_server 2,538,575K: Persistent 872,594K: com.sam.instrument (pid 2700) 6,862K: com.android.se (pid 1819) ... 24,735K: Persistent Service 24,735K: com.android.providers.media.module (pid 2664) 480,609K: Foreground 301,723K: com.sam.car.settings (pid 3164 / activities) ... 1,178,460K: Visible 1,022,509K: com.sam.carspeech (pid 3186) ... 776,717K: Perceptible 164,267K: com.sam.xpime (pid 6680) 8,965K: com.sam.car.ai (pid 3773) ... 85,791K: B Services 35,394K: com.sam.cardiagnosis (pid 6306) ... 177,923K: Cached 28,034K: com.sam.appstore (pid 3227) ... Total PSS by category: 1,876,492K: Native 790,289K: Dalvik 670,243K: .apk mmap 666,164K: GL mtrack 590,036K: .so mmap 568,452K: Unknown 133,191K: Dalvik Other 126,129K: Other mmap 90,951K: .art mmap 89,693K: .jar mmap 54,220K: Stack 37,382K: .dex mmap 20,804K: Ashmem 15,118K: .oat mmap 10,031K: .ttf mmap 6,072K: Other dev 0K: Cursor 0K: Gfx dev 0K: EGL mtrack 0K: Other mtrack Total RAM: 11,194,640K (status normal) Free RAM: 2,568,179K ( 177,923K cached pss + 1,919,984K cached kernel + 470,272K free) DMA-BUF: 1,063,552K ( 321,048K mapped + 742,504K unmapped) DMA-BUF Heaps: 716,532K DMA-BUF Heaps pool: 0K GPU: 1,027,356K ( 361,192K dmabuf + 666,164K private) Used RAM: 9,429,898K (6,765,282K used pss + 2,664,616K kernel) Lost RAM: 467,185K ZRAM: 272,432K physical used for 1,584,128K in swap (6,157,048K total swap) Tuning: 256 (large 512), oom 322,560K, restore limit 107,520K (high-end-gfx)
注:"Total PSS by OOM adjustment" 下的 Persistent 类型的app,被kill掉后会自动重启。
还可以 dumpsys meminfo <pid/包名>,例如:
# dumpsys meminfo $$ Applications Memory Usage (in Kilobytes): Uptime: 7517156 Realtime: 7517156 Pss Private Private Swap Rss Heap Heap Heap Total Dirty Clean Dirty Total Size Alloc Free ------ ------ ------ ------ ------ ------ ------ ------ Native Heap 180 180 0 0 180 0 0 0 Dalvik Heap 0 0 0 0 0 0 0 0 Stack 48 48 0 0 48 Other dev 0 0 0 0 352 .so mmap 123 116 0 0 1948 Other mmap 155 56 0 0 988 Unknown 348 348 0 0 348 TOTAL 854 748 0 0 3864 0 0 0 App Summary Pss(KB) Rss(KB) ------ ------ Java Heap: 0 0 Native Heap: 180 180 Code: 116 1948 Stack: 48 48 Graphics: 0 0 Private Other: 404 System: 106 Unknown: 1688 TOTAL PSS: 854 TOTAL RSS: 3864 TOTAL SWAP (KB): 0
1. 相关名词介绍
RSS(Resident Set Size):
这是进程当前在物理内存中占用的空间,包括进程本身和所有链接库。RSS是评估进程内存占用的一个重要指标,它直接反映了进程当前实际使用的物理内存量。但由于包含了共享库,用处不大。
PSS(Proportional Set Size):
与RSS不同,PSS考虑了共享内存的情况,它计算了每个进程对共享内存的贡献,并通过等比例来分配共享内存的使用量。PSS更适合用来比较不同进程的内存使用情况,因为它避免了重复计算共享内存的问题。
此数据非常有用,因为系统中所有进程的PSS都相加的话,就刚好反映了系统中的总共被占用的内存量。而当一个进程被销毁之后, 其占用的共享库那部分比例的PSS,将会再次按比例分配给余下使用该库的进程。
USS(Unique Set Size):
这是进程独占的物理内存量,不考虑共享库占用的内存。USS可以用来计算某个进程真正独占的内存资源。
USS是非常有用的数据,因为它反映了运行一个特定进程真实的边际成本(增量成本)。当一个进程被销毁后,USS是真实返回给系统的内存。当进程中存在一个可疑的内存泄露时,USS是最佳观察数据。
VSS(Virtual Set Size)
虚拟内存占用,包含共享库,以及分配但未使用内存。其大小还包括可能不在RAM中的内存(比如虽然malloc分配了空间,但尚未写入)。VSS 很少被用于判断一个进程的真实内存使用量,用处不大。
二、dumpsys meminfo系统字段说明
1. Total RAM
Total RAM: 13,221,176K (status normal)
Total RAM 的值等同于meminfo 中的 "MemTotal" 字段。表示系统可见物理内存总量,应该是释放给伙伴系统的物理内存页总量(不含被硬件永久保留的部分)。
status normal:AMS/LMKD 评估的内存水位状态(例如 normal/moderate/low/critical),由可用内存与阈值比较得出。
2. Free RAM
Free RAM: 2,717,384K ( 229,812K cached pss + 2,187,228K cached kernel + 300,344K free)
表示可较快回收或立即可用的内存。统计方法(框架层汇总):
cached pss:处于 cached 状态进程的 PSS 总和(可通过杀缓存进程回收)。
cached kernel:内核可回收缓存(page cache/slab 可回收等)。
free:真正空闲页(等价 cat /proc/meminfo 中的 MemFree)。
公式:Free RAM = cached pss + cached kernel + free。
3. DMA-BUF
DMA-BUF: 1,251,000K ( 396,340K mapped + 854,660K unmapped)
(1) 含义:系统中 DMA-BUF 共享缓冲总占用(常见于图形/多媒体零拷贝路径)。
统计:
mapped:当前被映射到某些地址空间(CPU/进程)可访问的 dmabuf。
unmapped:已分配但当前未映射的 dmabuf。
这部分通常属于内核/驱动管理内存,与 GPU、相机、编解码关联很大。
(2) DMA-BUF 这一行是这样来的:
a. DMA-BUF 总量
来源接口:Debug.getDmabufTotalExportedKb()。含义是系统里“所有导出的 dma-buf 总大小”。底层来源是读取 /sys/kernel/dmabuf/buffers ####目录下的统计结果(通过 native 库 dmabufinfo 聚合),不是简单固定单文件值。
b. mapped
来源接口:Debug.getDmabufMappedSizeKb()。含义是当前被进程地址空间映射到的 dma-buf 总量。底层方法是解析每个 /proc/<pid>/maps,找出 dma-buf 映射并累计。它是扫全进程 maps 得到的。
c. unmapped
框架直接算:unmapped = totalExportedDmabuf - dmabufMapped
"DMA-BUF: X (Y mapped + Z unmapped)" 这个打印,其中 X 来自 getDmabufTotalExportedKb(), Y 来自 getDmabufMappedSizeKb(), Z 由 X-Y 计算得到的。
4. DMA-BUF Heaps
DMA-BUF Heaps: 827,108K
(1) 含义:通过 dma-buf heaps 分配器导出的缓冲占用总量。来自 dma_heap 子系统的导出统计(vendor/kernel 实现略有差异)。与上面的 DMA-BUF 有关联,但口径未必完全相同(是否包含所有 exporter、统计时点差异等)。
(2) 它是“DMA-BUF heap exporter 的总导出量(KB)”
Java 层调用:Debug.getDmabufHeapTotalExportedKb()
native 层实现:android_os_Debug_getDmabufHeapTotalExportedKb()
再调用 meminfo 库:meminfo::ReadDmabufHeapTotalExportedKb(&size)
(3) 和 DMA-BUF: 的区别:"DMA-BUF:"是全局导出的 dma-buf 总量, 而"DMA-BUF Heaps:"只看 dma-buf heap 框架导出的总量,是其中的一个子集。
5. DMA-BUF Heaps pool
DMA-BUF Heaps pool: 0K
(1) 含义:dma-buf heaps 的池化预留内存(预分配池)占用。来自 heap pool 统计;值 0K 表示当前无池中预留或平台未启用该池。
(2) 统计方法是 框架 AppProfiler 在汇总内存时调用 Debug.getDmabufHeapPoolsSizeKb()。native JNI 是 android_os_Debug_getDmabufHeapPoolsSizeKb() 然后调用 meminfo::ReadDmabufHeapPoolsSizeKb(&size),返回 KB。
Debug.java 的注释写得比较明确:这个值来自 DMA-BUF heap pool 的内核统计,是读取 /sys/kernel/dma_heap/total_pools_kb 它本质上是“内核已汇总的 heap pool 总量”。
实测,cat /sys/kernel/dma_heap/total_pools_kb 得到的结果也是0.
6. GPU
GPU: 2,483,932K ( 517,164K dmabuf + 1,966,768K private)
(1) 含义:GPU 相关内存总占用。统计来源通常是 GPU 驱动/memtrack:
dmabuf:GPU 使用的共享缓冲(可与系统其他模块共享)。
private:GPU 驱动私有内存(不通过 dmabuf 共享)。
公式:GPU = dmabuf + private。
注意:这行常与 DMA-BUF 有交叉口径(不能简单重复相加到系统总量)。
(2) 统计方法
先取系统视角下的 GPU 总占用(KB), 调用链:AppProfiler -> Debug.getGpuTotalUsageKb -> JNI -> meminfo::ReadGpuTotalUsageKb()
再取 GPU 私有量,调用链:AppProfiler -> Debug.getGpuPrivateMemoryKb() -> JNI. 这个值通常依赖 memtrack HAL 或驱动提供的私有显存统计。
然后 gpu_dmabuf = gpu_total - gpu_private。
这一行是 framework 是通过 Debug JNI + libmeminfo/memtrack 得到的。
7. Used RAM
Used RAM: 12,267,733K (8,291,765K used pss + 3,975,968K kernel)
含义:当前认为“被占用且非空闲”的内存。
统计:
used pss:用户态进程(按 PSS 口径)占用,通常不含 cached pss。
kernel:内核占用(含不可回收与部分可回收口径,依 Android 版本实现有差异)。
公式:Used RAM = used pss + kernel。
8. Lost RAM
Lost RAM: 30,218K
含义:无法被上面分类精确覆盖的余量(“对账差额”)。
常见来源:保留区、页表/元数据、驱动特殊分配、四舍五入、并发采样时差等。
常见近似:Lost ≈ Total - Free - Used。
9. ZRAM
ZRAM: 600,392K physical used for 2,426,624K in swap (7,271,640K total swap)
含义:压缩交换分区(zram)状态。
其中:
physical used:zram 实际占用物理内存(压缩后)。
in swap:已换出到 swap 的逻辑数据量(压缩前)。对照 cat /proc/meminfo 看,其值等于 "SwapTotal" - "SwapFree".
total swap:系统配置的总 swap 容量, 对应 meminfo 的 “SwapTotal”。
压缩比 = in swap / physical used = 2,426,624 / 600,392 ≈ 4.04。
10. Tuning
Tuning: 256 (large 512), oom 322,560K, restore limit 107,520K (high-end-gfx)
(1) 含义:AMS/LMKD 的内存策略参数。
成员解释:
256:普通应用 memory class(MB)。
large 512:声明 largeHeap 应用可用的较大 heap class(MB)。
oom 322,560K:触发更激进回收/杀进程的关键阈值(与 minfree 档位相关)。
restore limit 107,520K:从“紧张状态”恢复时的阈值。
high-end-gfx:设备内存/图形能力档位标签(高端图形配置)。
(2) memory class解释
“普通应用 memory class (MB)” 指的是 Android 给普通应用进程设定的“建议 Java 堆大小上限档位”。可以把它理解为它是一个“内存预算值”。例如 256 就表示该设备上普通 app 的推荐堆大小是约 256MB。App 可以通过 ActivityManager.getMemoryClass() 读到这个值。
它主要针对 Java/Kotlin 堆(Dalvik/ART heap),不是整个进程的全部内存上限。native 内存、图形内存、映射内存等不直接算在这个值里。
堆持续增长到接近 VM 的 heap limit 时,更容易频繁 GC。再继续申请可能触发 OutOfMemoryError。系统内存紧张时,进程也更容易被 LMKD 回收(尤其后台)。
与 large 的区别是:memory class 是普通应用默认档位。large(如 large 512) 是声明 android:largeHeap="true" 的应用可拿到更高堆档位,对应 getLargeMemoryClass()。但 largeHeap 不是“无限内存”,也不保证一定能稳定拿满。
(3) 此版本 cat /proc/zoneinfo 看 min、low、high 水线分别为 73728KB、134544KB、195360KB。不是和这里对应的。
这个 oom 322,560K 是 ProcessList 里算出来的 LMKD minfree 阈值,阈值在 ProcessList.updateOomLevels(...) 里生成,系统先算一个缩放系数 scale(由总内存和分辨率共同决定)。再把每个 OOM 档位的 mOomMinFree[i] 从 low/high 模板插值得到。
11. 小结
(1) 这些行里有很多“子集关系”(例如 GPU dmabuf 属于 DMA-BUF 的一部分、DMA-BUF 又常落在 kernel 口径里),所以不要把所有行直接相加。
(2) Android 版本和厂商内核会改统计方法,字段名字相同也可能细节不同。做问题定位时建议同一机型同一版本横向对比趋势,而不是只看单次绝对值。
优秀BK:
dumpsys meminfo 的原理和应用: https://www.cnblogs.com/Linux-tech/p/12961295.html
posted on 2024-10-16 21:15 Hello-World3 阅读(385) 评论(0) 收藏 举报
浙公网安备 33010602011771号