移动性能测试 Android 性能测试实践 (三) Cpu

testly · May 19, 2015 · Last by nancyyang0409 replied at September 02, 2019 · 11580 hits
本帖已被设为精华帖!

Cpu篇

关于Android 的Cpu占用率需要注意以下三种情况:

1.空闲状态下的应用CPU消耗情况 简单说这种情况呢就是说被测应用在系统资源非常空闲的情况下的占用率,比如只开一个被测应用

2.中等规格状态下的应用CPU消耗情况 简单说这种情况就是后台已经有几个应用在运行已经并且消耗了系统的一些资源的情况下进行测试。

3.满规格状态下的应用CPU消耗情况 这个就不要说了,你们懂得!

数据采集方案:

1.

adb shell dumpsys cpuinfo

这里可以看到所有进程的Cpu占用率:

大家看第一个应用CPU占用率68%,这个过程是在用户(user)中花61%的时间,并在内核空间(kernel)花费7.1%的时间。

如果你想筛选出你自己的应用的话可以用下面这一段:

adb shell dumpsys cpuinfo |grep packagename 

2.使用top命令:

进入Adb shell

adb shell
top -m 10 -s cpu

可查看占用cpu最高的前10个程序(-t 显示进程名称,-s 按指定行排序,-n 在退出前刷新几次,-d 刷新间隔,-m 显示最大数量)

如果你想筛选出你自己的应用的话可以用下面这一段:

adb shell top -n 1| grep PackageName

拿到这些数据怎么用

1,你可以从代码里面获取:

(dumpsys)

adb shell  dumpsys  cpuinfo
    public static String GetCpu(String packageName) throws IOException {
String str3=null;
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("adb shell dumpsys cpuinfo $"+packageName);
try {
if (proc.waitFor() != 0) {
System.err.println("exit value = " + proc.exitValue());
}
BufferedReader in = new BufferedReader(new InputStreamReader(
proc.getInputStream()));
StringBuffer stringBuffer = new StringBuffer();
String line = null;
while ((line = in.readLine()) != null) {
stringBuffer.append(line+" ");
}
String str1=stringBuffer.toString();
String str2=str1.substring(str1.indexOf(packageName),str1.indexOf(packageName)+28);
str3=str2.substring(18,23);


} catch (InterruptedException e) {
System.err.println(e);
}finally{
try {
proc.destroy();
} catch (Exception e2) {
}
}
return str3;

}

}

(Top)


public static double cpu(String PackageName) throws IOException {
double Cpu = 0;
try{
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("adb shell top -n 1| grep "+PackageName);
try {
if (proc.waitFor() != 0) {
System.err.println("exit value = " + proc.exitValue());
}
BufferedReader in = new BufferedReader(new InputStreamReader(
proc.getInputStream()));
StringBuffer stringBuffer = new StringBuffer();
String line = null;
while ((line = in.readLine()) != null) {
stringBuffer.append(line+" ");


}
String str1=stringBuffer.toString();
String str3=str1.substring(str1.indexOf(PackageName)-43,str1.indexOf(PackageName));
String cpu= str3.substring(0,4);
cpu=cpu.trim();
Cpu=Double.parseDouble(cpu);

} catch (InterruptedException e) {
System.err.println(e);
}finally{
try {
proc.destroy();
} catch (Exception e2) {
}
}
}
catch (Exception StringIndexOutOfBoundsException)
{

System.out.print("请检查设备是否连接");

}

return Cpu;

}


2,直接 adb shell cat进去proc/cpuinfo/下面:

public String[] getCpuInfo() {  
String str1 = "/proc/cpuinfo";
String str2="";
String[] cpuInfo={"",""};
String[] arrayOfString;
try {
FileReader fr = new FileReader(str1);
BufferedReader localBufferedReader = new BufferedReader(fr, 8192);
str2 = localBufferedReader.readLine();
arrayOfString = str2.split("\\s+");
for (int i = 2; i < arrayOfString.length; i++) {
cpuInfo[0] = cpuInfo[0] + arrayOfString[i] + " ";
}
str2 = localBufferedReader.readLine();
arrayOfString = str2.split("\\s+");
cpuInfo[1] += arrayOfString[2];
localBufferedReader.close();
} catch (IOException e) {
}
return cpuInfo;
}

取完你可以这么用》:

配合一些场景去采集数据:

这样可以看到每个步骤消耗的资源情况

然后汇总数据分析(最好多取几次求平均值):

欢迎一起交流,一起进步 可以关注我的微信公众号:“测试开发进阶” - 点我关注

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 46 条回复 时间 点赞

话说

String  str3=str1.substring(str1.indexOf(PackageName)-43,str1.indexOf(PackageName));
String cpu= str3.substring(0,4);
cpu=cpu.trim();
Cpu=Double.parseDouble(cpu);

这个规则是啥。。。

testly #2 · May 19, 2015 作者

#1楼 @monkey 截取转换

#2楼 @testly 我知道。。你怎么保证,每个机器都能够准确的找到?

testly #4 · May 19, 2015 作者

#3楼 @monkey 设备不一样 包名一样啊

testly #5 · May 19, 2015 作者

#3楼 @monkey 我是拿包名前面位标准的

#4楼 @testly 。。。每个设备的top数据矩阵都不同的。。。。明白我的意思?

testly #7 · May 19, 2015 作者

#6楼 @monkey 明白!那用Cpuinfo 来取,怎样?

testly #8 · May 19, 2015 作者

#6楼 @monkey 我试过5台机器 三星 中兴 华为 HTC 谷歌 都测试过没有问题。。。所以其他机器我也没有去试过!也不敢保证可以取到

#8楼 @testly 肯定有不一样的。之前看到过好多了。。。。

#7楼 @testly cpuinfo没有尝试过。应该会好点吧

testly #11 · May 19, 2015 作者

#9楼 @monkey 恩,dumpsy cpuinfo里面的标准应该要好一点!

挺复杂的

@testly

我想问下,如何在window下 如何调用 adb shell 的命令,我使用runtime.exec("adb shell dumpsys ") ;这个命令,一直在报错,也试过在前面街上cmd.exe 但是还是不行呢,请教下,window写如何通过java 调用adb 命令???

testly #14 · May 20, 2015 作者

#13楼 @felixtest Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec(Command);
报什么错?

我想问一下,文中提到的三种规格:空规格,中等规格和满规格是说手机状态,而不是说对应用的操作吗?比如,空规格是指启动程序后按Home不进行任何操作,中等规格是正常操作App,满规格是执行Monkey。当然这可能会按实际需求去定,但一般情况是用哪种采样更合理呢?

testly #16 · May 20, 2015 作者

#15楼 @emily 既然是性能测试最好都涉及到为好咯!优先级的话!中》高》低

@testly
1、在windows 下,开始在没有输入str1的时候,提示检查连接设备,我就把修改了grep --> findstr ,发现提示如下:

2、根据提示,我又将findstr修改为 grep,打印如下:但是提示依然是设备连接问题,这个提示不友好哈,此时是可以获取到设备的信息的,如下:

总结:以上问题,认为java中的runtime.exec() 方法是执行windows系统下的命令,所以我使用了findstr,但是实际上Runtime获取当前的系统程序应是指Android,也就是Linux,我修改了grep,可以获取cpu的值,但是取 子字符中的角标越界问题我还在想,哈哈· 还是谢谢你哈~

testly #19 · May 20, 2015 作者

#18楼 @felixtest 恩恩,这句是将 String 转 double 然后切入Jfreechart 进行统计

@testly ,是的 这就Cpu=Double.parseDouble(cpu);,是不是需要结合jfreechart用的哈,单独用会报错,我直接使用String,就OK了~谢谢

testly #21 · May 20, 2015 作者

#20楼 @felixtest 恩,不客气

请问,你们执行性能测试的机器会用什么?会针对不同的机器做性能测试么?有必要么?

testly #23 · May 20, 2015 作者

#22楼 @shixue33 看你们的需求呢,要求不高的话可以拿一个普通机器看看数据跟别的应用对比对比就好啦! 我自己的话是有5个机器,但是呢真正测试的 就三个 一个低配,一个非主流、一个主流中高端机器

学习了,牛人。这两天学习一下jfreechart搞一下,遇到困难时,还望大神多多帮忙,O(∩_∩)O~

@testly dumpsy cpuinfo中进程的cpu占用会跟top基本一样么?平常使用这个命令的时候cpu信息更新的比较慢,知道这个命令数据更新的规则么?

testly #26 · May 25, 2015 作者

#25楼 @raowm520 不好意思,我没有注意到你的疑问!不会一样, dumpsys cpuinfo 里面是描述Cpu的使用详情 且里面的cpu占比是指Cpu所花的时间比比如用户活动消耗时间占比和内耗消耗时间占比,top是实际单进程的Cpu占用!这是我的理解!

@testly 好的,我自己也再看看

testly #28 · May 26, 2015 作者

#27楼 @raowm520 欢迎交流

hi,大神
我在尝试着用 adb shell top -d 1 | grep + packagename 命令去读取特定app的cpu使用率。大致的想法是这样的:通过这条命令,把所有的输出写到一个文件里,然后在汇总cpu占用的情况。
代码是这样的:
String path = "e:/cpu.txt";
int i = 0;
/*if(!haveDevices())
{
System.out.println("device not existing,please check ");
return ;
}
*/
try
{
Runtime rt = Runtime.getRuntime();

File myFilePath = new File(path);
if (!myFilePath.exists())
myFilePath.createNewFile();

FileWriter file = new FileWriter(myFilePath,true);
Process proc = rt.exec("adb shell top -d 1 | grep " + packagename ); //得到的CPU信息写到文件中
try{

if(proc.waitFor() != 0)
{
System.err.println("exit value = " + proc.exitValue()); //waitfor 返回值0 正常结束
}
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line;
StringBuffer strBuff = new StringBuffer();
while((line = reader.readLine()) != null)
{
//if(line != null)
//file.write(line + "\n") ; //仅保存含包名的
System.out.println(line);
}
}

运行之后发现cpu.txt为空,应该是reader也为空,不知道是什么鬼

testly #30 · May 28, 2015 作者

#29楼 @best1196 首先给你一点思路,你可以分两步,第一步先把想要的值取出来赋给一个对象!第二 把新建文件和输入的内容封装一下,再调用这个方法把对象传过去!

#30楼 @testly 本来想完全自动化的,不过被那个问题卡住了,现在的思路:先手动执行下那个命令,把他重定向到文件里,然后在读文件,这样就好处理了

对于best1196提出的这个问题,还是自己来解答下。
代码里需要添加 InputStream is = process.getErrorStream(); // 获取错误输出流
由于错误输出流一直没有被清空导致程序被阻塞,添加这行代码之后错误输出流就被清空了,当然就不会被阻塞了。
详细的内容可参考 http://249wangmang.blog.163.com/blog/static/52630765201261334351635/
多谢大神 @testly 不吝赐教,:D

testly #33 · May 28, 2015 作者

#32楼 @best1196 解决了就好!

hello 有查看到android5.0 如果需要使用runtime去执行dumpsys命令的话,添加android.permission.DUMP权限需要app是系统应用或赋予signatureOrSystem等级,但是添加了之后依然没作用,不知道有没有什么解决办法

testly #35 · May 29, 2015 作者

#34楼 @bh01251859 两个思路:第一个,你先手去获取一下 adb shell dumpsys cpuinfo 或者 adb shell top 如果手工获取不到
那就更不要提runtime了! 第二个,检查下手机root权限

很想问问大神最后的html的报告是怎么实现的啊??

testly #37 · June 08, 2015 作者

半夜了,新手加入,根本停不下来!感谢testerhome这个平台啊啊啊!坚持坚持!

—— 来自TesterHome官方 安卓客户端

dumpsys 拿到的是几个cpu的值,所以可能得到100+%的值,还是proc/pid/stat 靠谱点

#39楼 @jira xxxxxx:~ xxxxxxx$ adb shell dumpsys cpuinfo |grep com.xxx.xxx
107% 15524/com.xxx.xxx: 84% user + 23% kernel / faults: 2098 minor

请问,如何确定所取到的值是在操作该场景时的值呢,而且,场景应该都是一段时间的,您最后取到的这个场景的值是说进入该场景时的值么?

@testly 大神,我问一个小白问题,为什么我执行top -n 1这一句话需要3300+毫秒;还有就是我这手机没找到su文件,执行dumpsys cpuinfo会保存;

#42楼 @tiger07706 top load的数据比较多 不过3秒有点夸张了

大神,我在执行exec(top -n 1|grep 包名)时exitvalue为1,reader.readline()也无法获取数据,请帮忙看一下吧,谢谢了

在“配合一些场景去采集数据”这一节里面,你用的是jenkins吗?jenkins里面的脚本怎么写的,另外,手机要连上jenkins所在的服务器吧?

请问cpu这些数据取出来后,是否需要优化的判断标准是啥呢?

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up