一、概述
1.1 内存指标概念
Item
全称
含义
等价
USSUnique Set Size物理内存进程独占的内存
PSSProportional Set Size物理内存PSS= USS+ 按比例包含共享库
RSSResident Set Size物理内存RSS= USS+ 包含共享库
VSSVirtual Set Size虚拟内存VSS= RSS+ 未分配实际物理内存
故内存的大小关系:VSS >= RSS >= PSS >= USS
1.2 内存分析命令
常用的内存调优分析命令:
dumpsys meminfo
procrank
cat /proc/meminfo
free
showmap
vmstat
二 命令说明
1. dumpsys meminfo
dumpsys meminfo命令的输出结果分以下4部分:
序列
划分类型
排序
解释
1processPSS以进程的PSS从大到小依次排序显示,每行显示一个进程;
2OOM adjPSSNative/System/Persistent/Foreground/Visible/Perceptible/A Services/Home/B Services/Cached,分别显示每类的进程情况
3categoryPSS以Dalvik/Native/.art mmap/.dex map等划分的各类进程的总PSS情况
4total–总内存、剩余内存、可用内存、其他内存
命令内容:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52TotalPSSbyprocess://以process来划分
167128kB:com.android.systemui(pid4395)
124527kB:system(pid1192)
44213kB:com.android.settings(pid29256/activities)
41822kB:surfaceflinger(pid391)
...
TotalPSSbyOOMadjustment://以oom来划分,会详细列举所有的类别的进程,此处省略.
183683kB:Native
42024kB:surfaceflinger(pid388)
16740kB:mediaserver(pid471)
16040kB:zygote(pid494)
...
124527kB:System
344259kB:Persistent
69719kB:Foreground
49026kB:Visible
34005kB:Perceptible
7880kB:AServices
58689kB:Home
98352kB:BServices
94888kB:Cached
TotalPSSbycategory:// 以category划分
309449kB:Dalvik
230330kB:Native
145344kB:EGLmtrack
117797kB:.sommap
54389kB:.artmmap
44886kB:.dexmmap
32428kB:DalvikOther
31083kB:.oatmmap
29456kB:Stack
21782kB:Gfxdev
21733kB:Unknown
12695kB:.apkmmap
9367kB:Othermmap
2169kB:.ttfmmap
2062kB:Otherdev
38kB:.jarmmap
12kB:Ashmem
8kB:Cursor
0kB:GLmtrack
0kB:Othermtrack
//整体情况
TotalRAM:2857032kB(statusmoderate)
FreeRAM:1439488kB(94888cachedpss+344620cachedkernel+999980free)
UsedRAM:1280552kB(970140usedpss+310412kernel)
LostRAM:136992kB
ZRAM:4kBphysicalusedfor0kBinswap(524284kBtotalswap)
Tuning:256(large512),oom525000kB,restorelimit175000kB(high-end-gfx)
另外,可只输出某个pid或package的进程信息:
Java
1
2dumpsysmeminfo// 输出指定pid的某一进程
dumpsysmeminfo--package// 输出指定包名的进程,可能包含多个进程
2. procrank
功能: 获取所有进程的内存使用的排行榜,排行是以Pss的大小而排序。procrank命令比dumpsys meminfo命令,能输出更详细的VSS/RSS/PSS/USS内存指标。
最后一行输出下面6个指标:
totalfreebufferscachedshmemslab
执行结果:
Java
1
2
3
4
5
6
7
8
9
10
11root@Phone:/#procrank
PIDVssRssPssUsscmdline
43952270020K202312K136099K121964Kcom.android.systemui
11922280404K147048K89883K84144Ksystem_server
292562145676K97880K44328K40676Kcom.android.settings
5011458332K61876K23609K9736Kzygote
42392105784K68056K21665K19592Kcom.android.phone
479164392K24068K17970K15364K/system/bin/mediaserver
391200892K27272K15930K11664K/system/bin/surfaceflinger
...
RAM:2857032Ktotal,998088Kfree,78060Kbuffers,459780Kcached,312Kshmem,92392Kslab
3. cat /proc/meminfo
功能:能否查看更加详细的内存信息
Java
1
指令:cat/proc/meminfo
输出结果如下(结果内存值不带小数点,此处添加小数点的目的是为了便于比对大小):
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41root@phone:/#cat/proc/meminfo
MemTotal:2857.032kB//RAM可用的总大小 (即物理总内存减去系统预留和内核二进制代码大小)
MemFree:1020.708kB//RAM未使用的大小
Buffers:75.104kB//用于文件缓冲
Cached:448.244kB//用于高速缓存
SwapCached:0kB//用于swap缓存
Active:832.900kB//活跃使用状态,记录最近使用过的内存,通常不回收用于其它目的
Inactive:391.128kB//非活跃使用状态,记录最近并没有使用过的内存,能够被回收用于其他目的
Active(anon):700.744kB//Active = Active(anon) + Active(file)
Inactive(anon):228kB//Inactive = Inactive(anon) + Inactive(file)
Active(file):132.156kB
Inactive(file):390.900kB
Unevictable:0kB
Mlocked:0kB
SwapTotal:524.284kB//swap总大小
SwapFree:524.284kB//swap可用大小
Dirty:0kB//等待往磁盘回写的大小
Writeback:0kB//正在往磁盘回写的大小
AnonPages:700.700kB
Mapped:187.096kB//通过mmap()分配的内存,用于map设备、文件或者库
Shmem:.312kB
Slab:91.276kB//kernel数据结构的缓存大小,Slab=SReclaimable+SUnreclaim
SReclaimable:32.484kB//可回收的slab的大小
SUnreclaim:58.792kB//不可回收slab的大小
KernelStack:25.024kB
PageTables:23.752kB//以最低的页表级
NFS_Unstable:0kB//不稳定页表的大小
Bounce:0kB
WritebackTmp:0kB
CommitLimit:1952.800kB
Committed_AS:82204.348kB//评估完成的工作量,代表最糟糕case下的值,该值也包含swap内存
VmallocTotal:251658.176kB//总分配的虚拟地址空间
VmallocUsed:166.648kB//已使用的虚拟地址空间
VmallocChunk:251398.700kB//虚拟地址空间可用的最大连续内存块
对于cache和buffer也是系统可以使用的内存。所以系统总的可用内存为 MemFree+Buffers+Cached
4.free
主功能:查看可用内存,缺省单位KB。该命令比较简单、轻量,专注于查看剩余内存情况。数据来源于/proc/meminfo。
输出结果:
Java
1
2
3
4
5root@phone:/proc/sys/vm#free
totalusedfreesharedbuffers
Mem:285703218360401020992075104
-/+buffers:17609361096096
Swap:5242840524284
对于Mem行,存在的公式关系: total = used + free;
对于-/+ buffers行: 1760936 = 1836040 – 75104(buffers); 1096096 = 1020992 + 75104(buffers);
5. showmap
主功能:用于查看虚拟地址区域的内存情况
Java
1
用法:showmap-a[pid]
该命令的输出每一行代表一个虚拟地址区域(vm area)
Java
1
2
3
4
5root@phone:/#showmap-a10901
startendvirtualsharedsharedprivateprivate
addraddrsizeRSSPSScleandirtycleandirtyobject
------------------------------------------------------------------------------------------------------
f3b87000f3d850002040440040/dev/binder
start addr和end addr:分别代表进程空间的起止虚拟地址;
virtual size/ RSS /PSS这些前面介绍过;
shared clean:代表多个进程的虚拟地址可指向这块物理空间,即有多少个进程共享这个库;
shared: 共享数据
private: 该进程私有数据
clean: 干净数据,是指该内存数据与disk数据一致,当内存紧张时,可直接释放内存,不需要回写到disk
dirty: 脏数据,与disk数据不一致,需要先回写到disk,才能被释放。
功能与cat /proc/[pid]/maps基本一致。
6. vmstat
主功能:不仅可以查看内存情况,还可以查看进程运行队列、系统切换、CPU时间占比等情况,另外该指令还是周期性地动态输出。
用法:
Java
1
2
3
4Usage:vmstat[-niterations][-ddelay][-rheader_repeat]
-niterations数据循环输出的次数
-ddelay两次数据间的延迟时长(单位:S)
-rheader_repeat循环多少次,再输出一次头信息行
输入结果:
Java
1
2
3
4
5
6
7
8root@phone:/#vmstat
procsmemorysystemcpu
rbfreemappedanonslabincsfltusnisyidwair
2066343623283691519211396019627408029900
0066344423283691510811396018026007039900
0066347623283691521611396015422402059900
10663132232836915304113960179259011039900
2066312423283691509611396011017504039900
参数列总共15个参数,分为4大类:
procs(进程)
r: Running队列中进程数量
b: IO wait的进程数量
memory(内存)
free: 可用内存大小
mapped:mmap映射的内存大小
anon: 匿名内存大小
slab: slab的内存大小
system(系统)
in: 每秒的中断次数(包括时钟中断)
cs: 每秒上下文切换的次数
cpu(处理器)
us: user time
ni: nice time
sy: system time
id: idle time
wa: iowait time
ir: interrupt time
小结
dumpsys meminfo适用场景: 查看进程的oom adj,或者dalvik/native等区域内存情况,或者某个进程或apk的内存情况,功能非常强大;
procrank适用场景: 查看进程的VSS/RSS/PSS/USS各个内存指标;
cat /proc/meminfo适用场景: 查看系统的详尽内存信息,包含内核情况;
free适用场景: 只查看系统的可用内存;
showmap适用场景: 查看进程的虚拟地址空间的内存分配情况;
vmstat适用场景: 周期性地打印出进程运行队列、系统切换、CPU时间占比等情况;
MemAvailable:MemFree+Active(file)+Inactive(file)-(watermark+min(watermark,Active(file)+Inactive(file)/2))
file占用的内存是可以释放的,但是释放的过多,会导致swap发生
减去部分内存的目的是避免swap