统计 Android 应用的 CPU 和内存
Android 系统基于 Linux 的内核构建起来,因此统计应用消耗的内存和占用的 CPU 时非常方便,本文介绍统计 CPU 和内存的命令,以及实现自动化统计的思路
CPU 的统计Linux 提供了非常简单的一个命令
top
,可以查看应用的 CPU 和内存占用情况,Android shell 下也可以直接使用它,输入如下命令就能够在窗口中循环输出 CPU 占用靠前的应用进程
$ adb shell top
400%cpu 67%user 7%nice 63%sys 251%idle 1%iow 9%irq 2%sirq 0%host
PID USER PR NI VIRT RES SHR S[%CPU] %MEM TIME+ ARGS
2400 system 20 0 4.1G 64M 37M S 39.3 1.7 0:45.45 com.example+
1050 system 18 -2 4.3G 138M 94M S 15.0 3.8 0:40.05 system_server
3464 u0_a39 20 0 2.0G 238M 59M S 14.6 6.5 0:32.29 com.abc.test+
第 9 行 [%CPU] 和 第 10 行 %MEM 则分别对应进程的 CPU 占用率百分比和内存占用率百分比
这里 CPU 所在的列被中括号框选住,表示排序方式按 CPU 从高到低降序排列
另外,留意第一行第一列,显示的是 400%cpu,这是什么意思呢?
这表示 CPU 核心数不止一个,在这里有四个,所以就是 4 * 100%
想要查询这个命令传递参数的用法,可以输入
$ adb shell top --help
usage: top [-Hbq] [-k FIELD,] [-o FIELD,] [-s SORT] [-n NUMBER] [-d SECONDS] [-p PID,] [-u USER,]
Show process activity in real time.
-H Show threads
-k Fallback sort FIELDS (default -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)
-b Batch mode (no tty)
-d Delay SECONDS between each cycle (default 3)
-n Exit after NUMBER iterations
-p Show these PIDs
-u Show these USERs
-q Quiet (no header lines)
这里面重点提示一下
-p
参数,表示只输出指定进程 ID,-H
参数,表示输出线程的占用率
我们发现,这个命令只是把结果打印到窗口里,如果要保存到文件中做进一步分析,或者提供给开发排查问题,可以输入
$ adb shell top > file.txt
这样就保存到文件中了
另外,上面提到默认情况下是按 CPU 降序排列,使用
-s 列号
的参数可以按照其他列进行降序排列,比如按内存占用降序
$ adb shell top -s 10
Android 中,除了 top 命令外,还有一个命令用来统计最近一段时间内的 CPU 占用率,这在快速分析最近 CPU 占用时非常有用
$ adb shell dumpsys cpuinfo
Load: 7.88 / 8.13 / 5.81
CPU usage from 372745ms to 72694ms ago (2018-10-18 20:10:37.725 to 2018-10-18 20:15:37.776):
39% 2400/com.xxx.xxx.xx: 29% user + 10% kernel / faults: 708419 minor
15% 1050/system_server: 9.6% user + 5.5% kernel / faults: 29353 minor
13% 1863/com.android.phone: 9.5% user + 4.1% kernel / faults: 113330 minor
13% 3464/com.yy.yyy.yyyy: 8.5% user + 4.7% kernel / faults: 24530 minor
从输出内容中,可以读到,这是一段 20:10:37.725 到 20:15:37.776 这五分钟内的 CPU 占用率统计
这段时间里,占用最高的应用占比为 39%,它的包名是 com.xxx.xxx.xx
其中 29% 为用户态,10% 为内核态
CPU 占用率统计的原理是什么呢?我这里以 Android 8.1 系统来解读一下
每个应用启动以后,会随机分配到一个 ID 值,叫做
PID
,可以通过 ps
命令查询应用的包名时得到
$ adb shell ps |grep com.android.settings
system 4603 543 4378288 43428 0 0 S com.android.settings
这里第二列的数字就是 PID,4603
应用启动以后,需要 CPU 做运算时,就会占用 CPU 的时间片让它去替自己做事,系统就会在某个位置写入应用的 CPU 占用时间,要查看这个时间,可以输入命令,以下命令中的 4603,需要替换为实际情况下的 PID 值
$ adb shell cat /proc/4603/stat
4603 (ndroid.settings) S 543 543 0 0 -1 1077936448 8978 0 13 0 4 6 0 0 20 0 11 0 5699 4483366912 10857 18446744073709551615 1 1 0 0 0 0 4612 0 1073775864 0 0 0 17 3 0 0 0 0 0 0 0 0 0 0 0 0 0
其中第 14 和 15 列的数字,分表表示应用在用户态下的 CPU 时间以及在内核态下的 CPU 时间
依据是 LInux 系统 proc 描述
http://man7.org/linux/man-pages/man5/proc.5.html
这两个数求和便是应用从启动到现在,一共使用的 CPU 时间
想要求得某个时间段中 CPU 的占用时间,则在 T1 时间,抓一次此数值,经过一段时间后,在 T2 时间,再抓一次此数值,求 T2 和 T1 数值之差便得到该时间段内的占用时间
既然我们是计算应用的 CPU 占用率,那么从哪里获得系统的占用时间呢?答案如下
$ adb shell cat /proc/stat
cpu 227074 29957 236622 747320 1822 34855 6375 0 0 0
cpu0 67340 7410 77242 142887 526 21616 4121 0 0 0
cpu1 64458 8939 77368 157790 717 9491 1260 0 0 0
cpu2 53326 7030 40617 216464 321 2078 615 0 0 0
cpu3 41950 6578 41395 230179 258 1670 379 0 0 0
...
对于每个数字的含义,仍然可参考上述页面下 Linux 对 proc 的解释
这里将输出结果第一行 cpu 字段后面的数字求和,即得到当前时间系统 CPU 的占用时间
分别抓取 T1 时刻和 T2 时刻系统 CPU 的占用时间,求差数就得到这个时间段内整个系统对 CPU 的占用
那么我们就可以算出来应用在 T1 和 T2 时间段内的 CPU 占用率了
内存的统计内存的统计原理相比于 CPU 更加复杂,这里不展开来谈,我们先学习统计的方法
Android 中推荐使用
dumpsys
命令去统计内存,而不是使用 top,因为它们计算方式上略有差别,我们依据 Android 官方推荐为准,使用如下命令
$ adb shell dumpsys meminfo
从这个命令中,我们能提取到总的物理内存值
Total RAM: 3,706,588K (status normal)
如果启动的应用非常多,那么此命令有可能在默认超时时间 10 秒内统计不完,就会报错退出
增加一个超时参数 -t 秒数,就可以避免这种情况
$ adb shell dumpsys -t 30 meminfo
由于多数情况下,我们更关心某个应用的内存占用,可以指定它的包名或者 PID,去针对性的获得结果
$ adb shell dumpsys meminfo com.android.settings
# 或者
$ adb shell dumpsys meminfo 4603
** MEMINFO in pid 4603 [com.android.settings] **
Pss Private Private SwapPss Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 1318 1276 0 0 6144 3154 2989
Dalvik Heap 166 148 0 0 1466 954 512
Dalvik Other 137 136 0 0
Stack 40 40 0 0
Ashmem 0 0 0 0
Other dev 8 0 8 0
.so mmap 156 64 0 0
.apk mmap 2148 0 2048 0
.dex mmap 900 8 820 0
.oat mmap 75 0 0 0
.art mmap 477 356 0 0
Other mmap 10 4 0 0
Unknown 506 504 0 0
TOTAL 5941 2536 2876 0 7610 4108 3501
提取 Pss Total 列的 TOTAL 值即可
通过不带包名的命令获得总的内存值,就可以计算占用率了
另外要提醒的是,上述命令执行过程中会消耗一定的 CPU,如果正在统计 CPU,则尽量减少对内存的统计,以免对总 CPU 造成影响
henry.Woo 原创文章 31获赞 6访问量 6820 关注 私信 展开阅读全文作者:henry.Woo
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341