Item | 全称 | 含义 | 等价 |
---|---|---|---|
USS | Unique Set Size | 物理内存 | 进程独占的内存 |
PSS | Proportional Set Size | 物理内存 | PSS= USS+ 按比例包含共享库 |
RSS | Resident Set Size | 物理内存 | RSS= USS+ 包含共享库 |
VSS | Virtual Set Size | 虚拟内存 | VSS= RSS+ 未分配实际物理内存 |
内存的大小关系:VSS>=RSS>=PSS>=USS
获取所有进程的内存使用的排行榜,排行是以Pss的大小而排序,能输出详细的VSS/RSS/PSS/USS内存指标。
获取所有进程的内存使用的排行榜,排行是以Pss的大小而排序,能输出详细的VSS/RSS/PSS/USS内存指标。
查看可用内存,缺省单位KB。该命令比较简单、轻量,专注于查看剩余内存情况。数据来源于/proc/meminfo。
对于Mem行,存在的公式关系:total= used+free;对于-/+ buffers行: buffers/cache used=mem_used - mem_buffers
buffers/cache free = mem free + mem buffers
展示的是系统整体内存情况,内存项按类型进行分类:
日常使用经验总结:1)MemTotal:是除去系统底层预留内存之外,能被系统使用的总内存大小,正常情况下会比实际内存小一点,但是如果小太多的话属于预留不合理,需要看看原因,这属于先天不足,天花板过低。
2)MemFree、MemAvailable:前者是当前系统未被使用的内存,后者是当前系统可以被使用的内存(包括可以被回收的部分内存),意思就那个什么,挤挤还是有的。从经验上来说,如果当前MemAvailable底于总内存的1/10,那么系统可能会出现因为内存造成的卡顿,其中原因可能包括频繁回收内存造成的阻塞、耗时以及寻址难度加大变相地增加了内存分配的时间等等。
3)Buffers、Cached:前者用于缓存磁盘blocks以优化block I/O,后者用于缓存文件内容以优化文件1/O。部分内存是可被回收的,被算到MemAvailable中。MemAvailable ≈ MemFree+Buffers+Cached
4)Mlocked:被系统锁定的页面。比如系统中google 7.0加的PinnerService 就会有这个效果,把常用的内容锁定在内存中,避免频繁的内存回收与分配,优化但不限于提升io效率。典型的用空间换时间,如果是Android 2G及其以下内存的手机,建议关闭PinnerService,要啥自行车。PinnerService官方描述
5) SwapTotal, SwapFree:这就zram,如果为0就是没打开。SwapTotal是zram总空间大小, SwapFree是没交换的空间大小。
6)Slab:内核基于Buddy做了page的粗分,Slab基于Buddy做了内存二次划分,这部分就是基于SIab内存分配的内存大小。使用的函数是kmalloc/kfree。SReclaimable和SUnreclaim分别是Slab的可回收和不可回收部分(slab=SReclaimable+SUnreclaim),如果Slab比较大,可能是kernel debug开关被打开了(也不一定,具体看调试内容),而且 SUnreclaim也非常大的话,可能存在kernel泄漏。
7) Kernel内存可使用内存 Slab + KernelStack+PageTables。
dumpsys的源码结构其实很简单,只有一个dumpsys.cpp源码路径是: /frameworks/native/cmds/dumpsys/dumpsys.cpp在其main方法中,先通过defaultServiceManager(函数获得ServiceManager对象,然后根据dumpsys传进来的参数通过函数checkService来找到具体的service,并执行该service的dump方法,达到dump service的目的。
dumpsys meminfo对应的服务是:ActivityManagerService, 它从memBinder类的dump函数开始执行的。
主要收集内存信息并打印是在dumpApplicationMemoryUsage方法中做的,但是该方法比较大,就不列出来了,举个例子:
Debug.getMemoryInfo(pid,mi);/通过debug.java中的getMemoryInfo函数来获取当前进程的整体memory信息,获取的是 对应的/proc/$/smaps文件统计出来的信息。getMemoryInfo是个native方法,对应到android_os_Debug.cpp的 android_os_Debug_getDirtyPagesPid.
从代码看:这部分内容是从/proc/$/smaps获取的。
那么总结下dumpsys meminfo的出处:
很明显,dumpsys meminfo 获取的数据是从系统各个渠道汇集来的。
先总结下最下面的统计:Total RAM:内存总数,与proc/meminfo中的MemTotal一致。Free RAM: cached pss + cached kernel + cached ion + free手机剩余内存一般是看它
Used RAM: used pss+kernel+trace buffer+ion display+cma usage
Lost RAM:与cache ion有关
ZRAM:zram swap转换情况
Tuning:这一行主要是system的一些设置,没看过
查看单个进程内存详情
数据来源:
纵轴:
属性名 | 说明 |
---|---|
Native Heap | 在Native Code 中使用 malloc 分配出的内存 |
Dalvik Heap | Dalvik 虚拟机分配的空间,不包括它自身的开销。Dalvik 堆中和 Zygote 进程共享的部分算是 sharedDirty |
Dalvik Other | 类数据结构和索引占据的内存 |
Stack | 栈内存 |
Cursor | CursorWindow 占用的空间,与 SQL 有关 |
Ashmem | 匿名共享内存,此类内存与cache shrinker 关联,可以控制cache shrinker在适当时机回收这些共享内存 |
Gfx dev | /dev/kgsl-3d0 占用的内存 |
Other dev | 内部driver占用的内存 |
.so mmap | 映射的 .so(native)代码占用的内存 |
.jar mmap | Java 文件代码占用内存 |
.apk mmap | apk 代码占用内存 |
.ttf mmap | ttf 文件代码占用内存 |
.dex mmap | 映射的 .dex(Dalvik 或 ART)代码占用的内存 |
.oat mmap | 代码映像占用的 RAM 量。此映像在所有应用之间共享,不受特定应用影响 |
.art mmap | 堆映像占用的 RAM 量。此映像在所有应用之间共享,不受特定应用影响。尽管 ART 映像包含 Object 实例,它仍然不会计入您的堆大小 |
Other mmap | 其它文件占用的内存 |
横轴:
属性名 | 说明 |
---|---|
Pss Total | 实际使用的内存,这里考虑了与Zygote 的共享。任何独占的内存页直接计算它的PSS值,而和其它进程共享的页则按照共享的比例计算PSS值 |
Private Dirty | 进程私有的,相对磁盘数据有改动的内存 |
Private Clean | 进程私有的,相对磁盘数据没有修改的内存 |
SwapPss Dirty | Android 4.4的一个优化,swap to zRAM。牺牲CPU,减少内存。这两个值的区别在于内核是否是统计按比例分出的swap数据,是的输出为SwapPss Dirty。 |
Swap Dirty | Whether the kernel reports proportional swap usage |
Heap相关:
Heap Size | Heap Alloc | Heap Free | |
---|---|---|---|
Native Heap | 从mallinfo usmblks获得,代表最 大总共分配空间 | 从mallinfo uorblks获得,总共已分配 空间 | 从mallinfo fordblks获得,代表总 共剩余空间 |
Dalvik Heap | 从Runtime totalMemory()获得, Dalvik Heap总共的内存大小 | Runtime totalMemory()-freeMemory() , Dalvik Heap分配的内存大小 | 从Runtime freeMemory()获得, Dalvik Heap剩余的内存大小 |
App Summary:
属性名 | 内存组成 |
---|---|
Java Heap | Dalvik Heap 的 Private Dirty.art mmap 的 Private Dirty |
Native Heap | Native Heap 的 Private Dirty |
Code | .so mmap.jar mmap.apk mmap.ttf mmap.dex mmap.oat mmap的 Private Dirty + Private Clean |
Stack | Stack 的 Private Dirty |
Graphics | Gfx devEGL mtrackGL mtrack的 Private Dirty + Private Clean |
Private Other | Native HeapDalvik Heap- HEAP_UNKNOWN的Private Dirty + Private Clean |
System | Native HeapDalvik HeapHEAP_UNKNOWN的 Pss + SwapPss Dirty - Private Dirty - Private Clean |
TOTAL | Native HeapDalvik HeapHEAP_UNKNOWN的 Pss + SwapPss Dirty |
TOTAL SWAP PSS | Native HeapDalvik HeapHEAP_UNKNOWN的 SwapPss Dirty |
TOTAL SWAP (KB) | Native HEAPDalvik HeapHEAP_UNKNOWN的 Swap Dirty |
Object:
这里通常会通过看Activities、AppContexts来判断是否有内存泄漏,比如刚退出应用,查看Object中Activities是否为0,如果 不为0,则有Activity没有销毁,很有可能存在泄漏。