android /proc/ 目录下为我们提供了操作系统几乎所有的状态信息,当然也包含系统的内存使用信息,下面列举了一些对应内存使用情况的目录信息:
/proc/meminfo 机器的内存使用情况
/proc/pid/maps pid 为进程号,显示当前进程所长用的虚拟地址
cat /proc/pid/statm pid 为进程号,第二列为正在使用的物理内存大小
/proc 目录是一个虚拟的目录,其下面的文件和目录也都是虚拟的,不占用实际的存储空间,而是存在于系统内存之中。proc 以文件系统的方式为访问系统内核的操作提供接口,它是动态从系统内核中读出所需的信息。
参数官方描述
==> 注意单位为 kB,下面列举几种常见项的意义
rk3288:/ # cat /proc/meminfo
MemTotal: 2045192 kB
MemFree: 561972 kB
MemAvailable: 1360216 kB
Buffers: 2480 kB
Cached: 1093140 kB
SwapCached: 0 kB
Active: 494260 kB
Inactive: 814140 kB
Active(anon): 214588 kB
Inactive(anon): 219172 kB
Active(file): 279672 kB
Inactive(file): 594968 kB
Unevictable: 256 kB
Mlocked: 256 kB
HighTotal: 1564668 kB
HighFree: 443576 kB
LowTotal: 480524 kB
LowFree: 118396 kB
SwapTotal: 1022260 kB
SwapFree: 1022260 kB
Dirty: 132 kB
Writeback: 0 kB
AnonPages: 213064 kB
Mapped: 542300 kB
Shmem: 221004 kB
Slab: 89472 kB
SReclaimable: 61508 kB
SUnreclaim: 27964 kB
KernelStack: 7248 kB
PageTables: 17176 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 2044856 kB
Committed_AS: 32299816 kB
VmallocTotal: 499712 kB
VmallocUsed: 0 kB
VmallocChunk: 0 kB
CmaTotal: 16384 kB
CmaFree: 15064 kB
系统从加电开始到引导完成,BIOS等要保留一些内存,内核要保留一些内存,最后剩下可供系统支配的内存就是MemTotal。这个值在系统运行期间一般是固定不变的。
表示系统尚未使用的内存,MemUsed=MemTotal-MemFree 就是已被用掉的内存。
应用程序可用内存数,系统中有些内存虽然已被使用但是可以回收的,比如 cache/buffer、slab 都有一部分可以回收,所以 MemFree 不能代表全部可用的内存,这部分可回收的内存加上 MemFree 才是系统可用的内存,即:MemAvailable≈MemFree+Buffers+Cached
它是内核使用特定的算法计算出来的,是一个估计值。它与MemFree的关键区别点在于,MemFree是说的系统层面,MemAvailable是说的应用程序层面。
free 命令显示系统使用和空闲的内存情况,包括物理内存、交互区内存(swap)和内核缓冲区内存。
rk3288:/ # free
total used free shared buffers
Mem: 2094276608 1672122368 422154240 229789696 2912256
-/+ buffers/cache: 1669210112 425066496
Swap: 1046794240 90112 1046704128
第一部分 Mem 行解释:
1. total:内存总数
2. used:已经使用的内存数
3. free:空闲的内存数
4. shared:多个进程共享的内存数
5. buffers:缓存区内存数
第二部分(-/+ buffers/cache)行解释:
第二行可以理解成跟上面第一行的 total、used、free 这一些不对应,
一共两个值,第一个是 (-buffers/cache),另一个是 (+buffer/cache)的值
第一个值 (-buffers/cache):
数值为:(Mem)used - (Mem)buffers
含义为:应用程序真正使用的内存数,即所有应用程序已经使用的内存减去共享的内存数
第二个值 (+buffer/cache):
数值为:(Mem)free + (Mem)buffer
含义为:应用程序可使用到的内存数,即当前未使用的内存数加上共享的内存数
第三部分是交互内存的数,也就是通常所说的虚拟空间
Android procrank 是按照内存占用情况对进程进行排序。因为它需要遍历 /proc 下的所有进程获取内存占用情况,所以在运行时候需要有 root 权限。可用排序的有 VSS、RSS、PSS、USS。
首先说明一下应用内存耗用的几个单词的含义:
VSS- Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
RSS- Resident Set Size 实际使用物理内存(包含共享库占用的内存)
PSS- Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
- PSS 与 RSS 的区别是按比例分配,也就是如果三个进程都使用了同一个共享库(占30页内存),
那么 PSS 认为每个进程占10页内存
USS- Unique Set Size 进程独占的物理内存(不包含共享库占用的内存)
- USS 是非常有用的数据,因为它反映了运行一个特定进程真实的成本(增量成本)。
当一个进程被销毁后,USS 是真实返回给系统的内存。
当进程中存在一个可疑的内存泄露时,USS 是最佳观察数据。
一般来说内存占用大小有如下规律:VSS >= RSS >= PSS >= USS
procrank 默认是按照 PSS 降序排列:
rk3288:/ # procrank -h
Usage: procrank [ -W ] [ -v | -r | -p | -u | -s | -h ]
-v Sort by VSS.
-r Sort by RSS.
-p Sort by PSS.
-u Sort by USS.
-s Sort by swap.
(Default sort order is PSS.)
-R Reverse sort order (default is descending).
-c Only show cached (storage backed) pages
-C Only show non-cached (ram/swap backed) pages
-k Only show pages collapsed by KSM
-w Display statistics for working set only.
-W Reset working set of all processes.
-o Show and sort by oom score against lowmemorykiller thresholds.
-h Display this help screen.
运行如下截图:
rk3288:/ # procrank
PID Vss Rss Pss Uss Swap PSwap USwap ZSwap cmdline
444 1753072K 184792K 81893K 70136K 12K 0K 0K 0K system_server
939 1848736K 210904K 80151K 42500K 16K 0K 0K 0K com.google.android.gms.persistent
1123 1966424K 203472K 73869K 36412K 16K 0K 0K 0K com.google.android.gms
569 1743596K 170144K 62840K 50472K 16K 0K 0K 0K com.android.systemui
1169 1772968K 171796K 62526K 38948K 16K 0K 0K 0K com.google.android.googlequicksearchbox:search
547 1697384K 121448K 34972K 27716K 16K 0K 0K 0K com.google.android.inputmethod.latin
1047 1714948K 137648K 32207K 18104K 16K 0K 0K 0K com.android.launcher3
325 1560208K 118160K 26989K 15632K 32K 16K 16K 15K zygote
10719 1697540K 97676K 24332K 19272K 16K 0K 0K 0K com.android.vending
10847 1813588K 126940K 23057K 4188K 16K 0K 0K 0K com.google.android.gms.unstable
971 1725516K 105736K 22103K 3280K 16K 0K 0K 0K com.google.android.googlequicksearchbox:interactor
626 1661076K 95856K 17894K 11976K 16K 0K 0K 0K com.android.phone
2538 1650844K 84140K 10332K 5172K 16K 0K 0K 0K com.google.android.setupwizard
Android 提供的 dumpsys 工具可以用于查看感兴趣的系统服务信息与状态,可以通过下面的命令查看本设备所支持查看的所有 service 信息
dumpsys | grep "DUMP OF SERVICE"
DUMP OF SERVICE mount:
DUMP OF SERVICE netd:
DUMP OF SERVICE netd_listener:
DUMP OF SERVICE netpolicy:
...
dumpsys 支持的 service 非常多,可以通过 -h 查看相关的 service 帮助信息,以 meminfo 为例演示:
rk3288:/ # dumpsys meminfo -h
meminfo dump options: [-a] [-d] [-c] [-s] [--oom] [process]
-a: include all available information for each process.
-d: include dalvik details.
-c: dump in a compact machine-parseable representation.
-s: dump only summary of application memory usage.
-S: dump also SwapPss.
--oom: only show processes organized by oom adj.
--local: only collect details locally, don't call process.
--package: interpret process arg as package, dumping all
processes that have loaded that package.
--checkin: dump data for a checkin
If [process] is specified it can be the name or
pid of a specific process to dump.
dumpsys meminfo 后面可以加单个进程名查看某进程的内存耗用信息
rk3288:/ # dumpsys meminfo com.android.launcher3
Applications Memory Usage (in Kilobytes):
Uptime: 18025666 Realtime: 22799195
** MEMINFO in pid 1047 [com.android.launcher3] **
Pss Private Private SwapPss Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 9541 9408 0 0 14336 10830 3505
Dalvik Heap 1875 1828 0 0 5102 2551 2551
Dalvik Other 554 552 0 0
Stack 36 36 0 0
Ashmem 2 0 0 0
Other dev 58 0 56 0
.so mmap 4711 236 1556 0
.apk mmap 5792 0 104 0
.ttf mmap 296 0 80 0
.dex mmap 3480 4 1908 0
.oat mmap 2174 0 0 0
.art mmap 875 520 4 0
Other mmap 436 4 0 0
Unknown 614 604 0 0
TOTAL 30444 13192 3708 0 19438 13381 6056
App Summary
Pss(KB)
------
Java Heap: 2352
Native Heap: 9408
Code: 3888
Stack: 36
Graphics: 0
Private Other: 1216
System: 13544
TOTAL: 30444 TOTAL SWAP PSS: 0
Objects
Views: 113 ViewRootImpl: 1
AppContexts: 10 Activities: 1
Assets: 6 AssetManagers: 9
Local Binders: 27 Proxy Binders: 40
Parcel memory: 33 Parcel count: 51
Death Recipients: 2 OpenSSL Sockets: 0
WebViews: 0
SQL
MEMORY_USED: 963
PAGECACHE_OVERFLOW: 550 MALLOC_SIZE: 117
DATABASES
pgsz dbsz Lookaside(b) cache Dbname
4 60 73 7/29/6 /data/user/0/com.android.launcher3/databases/launcher.db
4 456 60 88/28/5 /data/user/0/com.android.launcher3/databases/app_icons.db
4 20 37 2/26/3 /data/user/0/com.android.launcher3/databases/widgetpreviews.db
比较简单的理解是:
C/C++ 申请的内存空间在 native heap 中,而 java 申请的内存空间则在 dalvik heap 中。
dalvik heap 是 dalvik 虚拟机分配的内存,因为每一个应用都有一个虚拟机实例。
项解释如下:
几个概念解释:
- Pss
表示进程占用的实际内存,将跨进程共享页也加进来,进行比例计算 Pss。
- Dirty 与 clean
进程独占内存,也就是进程销毁时可以回收的内存容量。
通常 Private Dirty 内存是最重要的部分,因为只被自己进程使用。Dirty内存是已经被修改的内存页,因此必须常驻内存
* .so mmap & .dex mmap ... mmap
映射本地或虚拟机代码到使用的内存中。
* Unknown
无法归类的其他项。主要包括大部分的本地分配。
* Native Heap native
代码申请的内存, 堆和栈,及静态代码块等。
* TOTAL
进程总使用的实际内存。
*Objects
显示持有对象的个数。这些数据也是分析内存泄漏的重要数据,如 activity
可以通过不断查看应用进程的 native heap 和 dalvik heap szie 值,如果这两个值不断增大,则说明可能存在未释放内存的情况。