Android性能测试之CPU


Android性能测试


性能测试是手机应用测试中很重要的一个模块。 

一般情况下,性能测试主要关注的指标有:CPU、内存占用、电量消耗、GPU、FPS、网络流量、电池温度等等。 

后续我们将从这些指标出发,介绍性能测试方面的一些探索。


CPU性能测试


今天介绍的是CPU相关的性能测试。


总体介绍

CPU使用率的获取,当前主要有如下三种方案: 

1. 基于adb shell dumpsys cpuinfo的方式 

2. 读取/proc/pid/stat的方式 

3. 基于Linux的top命令


基于dumpsys cpuinfo的方案


Android提供了dumpsys的方式可以获取很多系统相关信息,比如meminfo,cpuinfo等。 

所以我们可以使用如下命令来获取CPU使用率:



如图可见,从第三行开始,每行表现一个PID对应的CPU使用情况。 

对应的格式是第一列数据为CPU使用率,第二列为PID/包名, 第三列为对应详细使用率情况。


这个方案可以很方便的获取CPU使用率,但是不足的一点是延迟较高,更新较慢。 

在输出的第二行显示了,当前的cpuinfo数据已经是90秒之前的信息。


读取/proc/pid/stat的方式


Linux层有公共目录。很多公共信息资源由两个虚拟的文件系统提供: 

/proc:包括内存,CPU,网络等 

/sys:设备驱动,网络环境(/sys/class/net/)等


通过/proc这个伪文件系统,我们可以和内核内部数据结构进行交互,获取有关进程的有用信息。


首先我们可以通过/proc/stat来获取CPU的总体使用情况:


可以看到第一行是CPU的使用情况,后面依次是每个核的使用情况。数据空格隔开,以第一行为例,每列的含义如下: 


cpu:表示名称 

user(1843147):从系统启动开始累计到当前时刻,用户态的CPU时间(单位:jiffies) ,不包含nice值为负进程。1 jiffies=0.01秒 


nice(161426):从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间(单位:jiffies) 


system (1338063) 从系统启动开始累计到当前时刻,核心时间(单位:jiffies) 


idle (10047312) 从系统启动开始累计到当前时刻,除硬盘IO等待时间以外其它等待时间(单位:jiffies) 


iowait (165356) 从系统启动开始累计到当前时刻,硬盘IO等待时间(单位:jiffies) 

 

irq (381) 从系统启动开始累计到当前时刻,硬中断时间(单位:jiffies) 


softirq (273341) 从系统启动开始累计到当前时刻,软中断时间(单位:jiffies)


总的CPU时间 cpu_time = user + system + nice + idle + iowait + irq + softirq


然后,通过如下命令获取单个PID的CPU时间:

输出中第一列为PID,第14、15列分别为: 

utime=2507,该任务在用户态运行的时间,单位为jiffies 

stime=951,该任务在核心态运行的时间,单位为jiffies


该PID的CPU时间 pid_cpu_time = utime + stime


因为两次计算的CPU时间都是总量,所以需要每个interval内保存上次的history值,最后得出的CPU使用率为: 

CPU% = (pid_cpu_time - old_pid_cpu_time) / (cpu_time - old_cpu_time) * 100%


同样的,想要精确获取CPU使用率,可以通过每个pid对应的数据并累加获得。


这个方案也可以很方便的获取CPU使用率,但是实际中也会发现存在问题: 

1. 文件权限,adb shell中获取/proc/pic/stat文件信息时可能会碰到permission deny的情况。 

2. 需要依次去获取每个pid数据,一定程度上不能保证时间一致性。


基于top命令的方案


因为Android系统基于的是Linux Kernel,而每个App都是以独立进程的形式运行,所以很自然的想到可以尝试用Linux下的top命令来获取App的CPU使用率。


基本命令为:adb shell top


常用参数一般有如下: 

-m:表示需要展示的进程数目 

-n:结束前需要刷新多少次 

-d:刷新间隔(单位秒) 

-s:按照什么列排序(cpu,vss,rss,thr)


如图:


可以看到输出的信息里面主要包括: 

PID(进程ID),CPU%(cpu使用率),VSS(虚拟内存使用量),RSS(实际物理内存使用量)等等。


我们一般关心的数据列就是CPU%。


所以我们可以很方便的实现基于TOP获取CPU使用率的方案,伪代码如下:


但是实际环境中,我们会发现经常获取到奇怪的数据。 

原来在不同的手机上,top命令的输出结构可能会不同,有时候并不是第三列。 

所以我们可以先使用如下命令来获取下top的输出格式:

然后根据对应CPU%所在列来获取对应的CPU使用率数据,伪代码如下:


这时,我们已经可以正常的获取到CPU使用率了。 

但是根据输出我们会发现,一行数据对于一个PID也就是一个进程,而这样的CPU使用率仅仅为App的主程序的CPU使用率,很多App会存在多进程,如启动一些后台服务,如图为微信的进程信息: 



如果需要精确统计App的CPU使用率,其实我们需要将这个App的所有进程的CPU使用率相加。


但是如何获知同属于一个App的所有进程呢? 

其实Android对Linux的uid进行了改造,并用于实现App的沙箱机制,每个App对应了一个uid。


对于普通的用户应用,在App安装时,Android就会赋予了一个id即uid,App的所有进程都由这个uid启动。 

所以,我们可以根据uid来筛选出同属于一个App的进程,只需要将上述代码增加获取uid列以及uid列的判断即可。


最后,我们只需要定时的去执行获取CPU使用率的函数即可得到CPU性能测试结果。


作者介绍



洪至远,百度平台测试部高级测试开发工程师,负责Android自动化测试技术的提升,从零开始设计并实现了SmartMonkey,Android混合脚本测试服务,Android测试脚本录制工具等,极大的提升了Android自动化测试能力。


寻找移动测试领域最擅长写作的人

长期有效,期待自荐欢迎推荐。

1、希望你在测试圈摸爬滚打依旧热情不减,乐于分享技术总结、项目经验,亦或是对行业的所想所感。原创内容或翻译稿件均可,文体不限,字数不限。

2、你可以收获,稿酬-真金白银、名望-滚滚而来。

3、投稿邮箱:zhaxiaodan@baidu.com(注明投稿)。



大咖招募
欢迎App研发/测试方面的大牛来投稿,开设专栏。我们提供丰厚的稿酬,预约个人专访,帮助建立个人技术品牌!
立即投稿

我要评论

字数不能超过140字,谢谢!
提交

评论({{allComments.length}})

{{comment.create_time.substr(0,16)}}

显示所有评论
复制成功!