adb命令 – 性能相关
内存
查看内存信息
adb shell dumpsys meminfo #获取pid
adb shell dumpsys meminfo pid
dumpsys meminfo:观察整体内存
smaps:观察整体内存的详细组成
** MEMINFO in pid 28803 [com.tencent.mobileqq] **
Pss Private Private SwapPss Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 6750 6748 0 52528 90112 71888 18223
Dalvik Heap 27231 27220 0 864 36380 28188 8192
Dalvik Other 2148 2148 0 3628
Stack 20 20 0 24
Ashmem 0 0 0 0
Other dev 36 0 36 0
.so mmap 2555 72 1952 2643
.jar mmap 382 0 0 0
.apk mmap 377 0 64 0
.ttf mmap 0 0 0 0
.dex mmap 31717 16 23524 3592
.oat mmap 211 0 0 0
.art mmap 18264 18040 20 18624
Other mmap 633 308 244 0
GL mtrack 840 840 0 0
Unknown 1448 1448 0 5102
TOTAL 179617 56860 25840 87005 126492 100076 26415
App Summary
Pss(KB)
------
Java Heap: 45280
Native Heap: 6748
Code: 25628
Stack: 20
Graphics: 840
Private Other: 4184
System: 96917
TOTAL: 179617 TOTAL SWAP PSS: 87005
私有内存(Dirty and Clean):
进程独占内存。也就是进程销毁时可以回收的内存容量。通常private Dirty内存是最重要的部分,因为只被自己进程使用。Dirty内存是已经被修改的内存页,因此必须常驻内存(因为没有swap);Clean内存是已经映射持久文件使用的内存页(例如正在被执行的代码),因此一段时间不使用的话就可以置换出去。
Pss是指实际使用的物理内存,考虑了在进程之间共享RAM页的情况。进程独占的RAM页会直接计入其PSS值,而与其他进程共享的RAM页则会按相应比例计入PSS值。例如,两个进程之间共享的 RAM 页会将其一半的大小分别计入这两个进程的 PSS 中。
可通过procrank命令查看
Item | 全称 | 内存形式 | 统计范围 | 描述 |
---|---|---|---|---|
USS | Unique Set Size | 物理内存 | 进程独占的内存 | 单个进程的全部私有内存大小,亦即全部被该进程独占的内存大小 |
PSS | Proportional Set Size | 物理内存 | Pss =Uss+按比例包含共享库 | 描述系统内存整体使用 |
RSS | Resient Set Size | 物理内存 | RSS=USS+包含共享库 | 指单个进程实际占用的内存大小,不是精确描述 |
VSS | Virtual Set Size | 虚拟耗用内存 | VSS = RSS+未分配实际物理内存(包含共享库占用的内存) | 是单个进程全部可访问的地址空间 |
内存的大小关系:VSS>RSS>=PSS>=USS
在实际分析中,一般是以PSS的内存为准,且也是最符合实际情况的统计值
通常我们需要关注PSS TOTAL 和 Private Dirty
匿名共享内存(Anonymous Shared Memory-Ashmem。Android匿名共享内存是基于Linux共享内存的,都是在tmpfs文件系统上新建文件,并将其映射到不同的进程空间,从而达到共享内存的目的,只是,Android在Linux的基础上进行了改造,并借助Binder+fd文件描述符实现了共享内存的传递。
参数分析:
纵轴
参数 | 含义 |
---|---|
Native Heap | Native代码分配的内存,虚拟机和Android框架分配内存,如C\C++堆的内存。 |
Dalvik Heap | Java对象分配的占据内存,包括它自身的开销;Dalvik堆中和zygote进程共享的部分算是sharedDirty。 |
Dalvik Other | 类数据结构和索引占据内存 |
Stack | 堆内存 |
Ashmem | 匿名共享内存,此类内存与cache shrinker关联,可以控制cache shrinker在适当时机回收这些共享内存。通过分配一个多个进程可以共享的带名称的内存块实现内存共享。 |
Other dev | 内部driver占用的内存 |
.so mmap | 映射的.so(native) 占用的内存,通常为C、C++库代码 |
.jar mmap | java文件代码占用的内存 |
.apk mmap | apk代码占用的内存 |
.ttf mmap | ttf文件代码占用的内存 |
.dex mmap | 映射的.dex(Dalvik 或ART)代码占用的内存。类函数的代码和常量占用的内存,dex mmap是映射classex.dex文件,Dalvik虚拟机从dex文件加载类信息和字符串常量等。Dex文件有索引区和Data区 |
oat mmap | 代码映射占用的内存。此映像在所有应用之间共享,不受特定应用影响 |
.art mmap | 堆映像占用的内存,此映像在所有应用之间共享,不受特定应用影响。尽管ART映射包含Object实例,它仍然不会计入堆的大小 |
Other mmap | 其它文件占用的内存 |
unknow | 系统无法将其分类到其他更具体的一个项中的任何 RAM 页 |
total | 进程占用的按比例分摊的内存大小 (PSS) RAM 总容量,等于上述所有 PSS 字段的总和 |
Pss | 进程各部分内存的消耗,是所有进程pss相加得到系统占用内存的总和。 |
横轴
参数 | 含义 |
---|---|
Pss Total | 某一项Pss的总值。 |
Private Dirty | 私有驻留内存。是仅分配给应用堆的实际RAM,包含了自己的分配和zygote分配页,这些分配页自从zygote派生应用进程以来已被修改。即使你的进程已经退出,该内存也不会被释放 |
Private Clean | 进程私有的,相对磁盘数据没有使用修改的内存。 |
SwapPss Dirty | 一些Android设备确实使用了内存交换,但它们使用的是内存而不是闪存。Linux有一个称为ZRAM的特性,它可以压缩页面,然后将它们交换到一个特殊的RAM区域,并在需要时再次解压它们。因此,“交换肮脏”中列出的页面很可能是在ZRAM中。 |
Heap Size | Dalvik Heap总共的内存大小 |
Heap Alloc | 所有应用实例分配的内存,包括了应用从zygote分享的内存 |
Heap Free | 空闲内存 |
查看单个应用最大内存限制
getprop | grep heapgrowthlimit
CPU
实时显示流程活动。
top [-Hbq] [-k FIELD,] [-o FIELD,] [-s SORT] [-n NUMBER] [-m LINES] [-d SECONDS] [-p PID,] [-u USER,]
参数:
参数 | –help | 描述 |
---|---|---|
-H | Show threads | 显示线程 |
-k | Fallback sort FIELDS (default -S,-%CPU,-ETIME,-PID) | 回退排序字段(默认为- s,-%CPU,- etime,- pid) |
-o | Show FIELDS (def PID,USER,PR,NI,VIRT,RES,SHR,S,%CPU,%MEM,TIME+,CMDLINE) | 显示字段 |
-O | Add FIELDS (replacing PR,NI,VIRT,RES,SHR,S from default) | 添加字段 |
-s | Sort by field number (1-X, default 9) | 按字段编号排序(1-X,默认为9) |
-b | Batch mode (no tty) | 批处理模式(无tty) |
-d | Delay SECONDS between each cycle (default 3) | 刷新时间间隔(默认3) |
-m | Maximum number of tasks to show | 要显示的最大任务数 |
-n | Exit after NUMBER iterations | 刷新次数 |
-p | Show these PIDs | 显示pid |
-u | Show these USERs | 显示用户 |
adb shell top -m 10
Tasks: 670 total, 1 running, 664 sleeping, 2 stopped, 3 zombie
Mem: 7.3G total, 6.8G used, 484M free, 6.8M buffers
Swap: 4.0G total, 2.1G used, 1.8G free, 3.0G cached
800%cpu 15%user 0%nice 12%sys 773%idle 0%iow 0%irq 0%sirq 0%host
PID USER PR NI VIRT RES SHR S[%CPU] %MEM TIME+ ARGS
11386 u999_a208 20 0 7.2G 101M 66M S 9.6 1.3 12:47.68 com.tencent.mm:+
1441 system 18 -2 11G 315M 182M S 7.3 4.1 527:28.46 system_server
11255 shell 20 0 29M 4.7M 3.4M R 2.3 0.0 0:01.83 top -m 10
293 root RT 0 0 0 0 S 2.0 0.0 25:35.49 [irq/36-5-0034]
3591 u0_a208 20 0 7.5G 343M 278M S 1.3 4.5 0:56.73 com.tencent.mm
302 root 20 0 0 0 0 D 1.3 0.0 12:23.64 [psl_thd]
10047 root 20 0 0 0 0 I 0.3 0.0 0:00.41 [kworker/2:2]
7969 root 20 0 0 0 0 I 0.3 0.0 0:03.60 [kworker/0:3]
2548 root 20 0 0 0 0 I 0.3 0.0 0:01.93 [kworker/1:4]
31542 root 20 0 0 0 0 I 0.3 0.0 0:04.68 [kworker/u16:9]
CPU占用率:
User | 用户进程 |
Nice | 优先值为负的进程所占用的CPU时间 |
Sys | 系统进程 |
Idle | 除IO等待时间以外的其它等待时间 |
iow | IO等待时间 |
irq | 硬中断时间 |
sirq | 软中断时间 |
进程属性:
PID | 进程id |
USER | 进程所属用户 |
PR | 进程优先级 |
NI | nice值。负值表示高优先级,正值表示低优先级 |
VIRT | 进程使用的虚拟内存总量,单位kb |
RES | 进程使用的、未被换出的物理内存大小,单位kb |
SHR | 共享内存大小,单位kb |
S | 进程状态。D=不可中断的睡眠状态 R=运行 S=睡眠 T=跟踪/停止 Z=僵尸进程 |
%CPU | 上次更新到现在的CPU时间占用百分比 |
%MEM | 进程使用的物理内存百分比 |
TIME+ | 进程使用的CPU时间总计,单位1/100秒 |
ARGS | 变量名(进程名称/命令名/命令行) |
VIRT虚拟内存
VIRT=SWAP+RES
进程“需要的”虚拟内存大小,包括进程使用的库、代码、数据,以及malloc、new分配的堆空间和分配的栈空间等;
假如进程新申请10MB的内存,但实际只使用了1MB,那么它会增长10MB,而不是实际的1MB使用量。
VIRT高是因为分配了太多地址空间导致。
RES实际占用内存
RES=CODE+DATA
进程当前使用的内存大小,包括使用中的malloc、new分配的堆空间和分配的栈空间,但不包括swap out量;
包含其他进程的共享;
如果申请10MB的内存,实际使用1MB,它只增长1MB;
SHR:
除了自身进程的共享内存,也包括其他进程的共享内存;
虽然进程只使用了几个共享库的函数,但它包含了整个共享库的大小;
计算某个进程所占的物理内存大小公式:RES – SHR;
swap out后,它将会降下来。
进程
adb shell ps -P -p -t -x -c [pid] [name] [ | grep ]
参数说明:
-P 显示调度策略,通常是bg或fg,当获取失败将会是un和er
-p 显示进程的优先级和nice等级
-t 显示进程下的线程列表
-x 显示进程耗费的用户时间和系统时间,格式(u:0, s:0),单位为:秒
-c 显示进程耗费的CPU时间(低于4.0版本可能不兼容)
[pid] 过滤指定的进程PID
[name] 过滤指定的进程NAME
S状态值
状态值 | 说明 |
---|---|
D | 不可中断的睡眠态 |
R | 运行态 |
S | 睡眠态 |
T | 被跟踪或已停止 |
Z | 僵尸态 |
W | 进入内存交换(从内核2.6开始无效) |
X | 死掉的进程 |
< | 高优先级 |
N | 低优先级 |
L | 有些页被锁进内存 |
s | 包含子进程 |
l | 多线程,克隆线程 |
+ | 位于后台的进程组 |
USER PID PPID VSZ RSS WCHAN ADDR S NAME
root 1 0 84476 4496 0 0 S init
root 2 0 0 0 0 0 S [kthreadd]
root 4 2 0 0 0 0 I [kworker/0:0H]
root 6 2 0 0 0 0 I [mm_percpu_wq]
root 7 2 0 0 0 0 S [ksoftirqd/0]
root 8 2 0 0 0 0 I [rcu_preempt]
参数说明:
参数 | 说明 |
---|---|
USER | 进程当前所属的用户 |
PID | 进程ID |
PPID | 父进程ID |
VSZ | 进程的虚拟内存大小,以KB为单位 |
RSS | 进程实际占用的内存大小,以KB为单位 |
WCHAN | 进程正在睡眠的内核函数名称,该函数名称是从/root、system.map文件中读取的,0代表进程处于运行态;否则代表内核地址(休眠态) |
参考meminfo&dumpsys meminfo PID 查看单进程内存信息详解&性能优化之借助adb shell ps /top 指令详细分析进程