性能测试工具 Android 性能测试实践 (二) 实时监控工具 (更新了~)

testly · 2015年05月18日 · 最后由 江上雨233 回复于 2020年09月01日 · 15291 次阅读
本帖已被设为精华帖!

前言

各位 这个工具是本人写的非常简陋体验也非常一般,大家手下留情,不要吐槽!能用上的拿去用吧!

工具下载地址:
64 位:
http://yunpan.taobao.com/s/1ZgCzvQlHbz
提取码:
ZV5odp

32 位:
http://yunpan.taobao.com/s/2kUMvT291UZ
提取码:
e1dyRp

工具说明

1,一定要是 Root 过的 Android 主流的手机
2,一定要有 Adb 环境(Android Debug Bridge)如果没有的话我文件里面放了

把这个文件夹 路径放到环境变量里面去,Path 下面哦
放完后 check 一下:

这样环境就 Ok 了

工具的原理

Cpu 取值:

adb shell top -n 1| grep "+PackageName

在代码怎么取呢?看下面

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));
      //System.out.println(str3);
       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;

}


内存取值:

adb shell dumpsys meminfo "+PackageName

public static double GetFlow(String PackageName) throws IOException {
      double str3=0;
      String Pid=PID(PackageName);
  try{
      Runtime runtime = Runtime.getRuntime();
   /*   Process proc2 = runtime.exec("");*/
      Process proc = runtime.exec("adb shell cat /proc/"+Pid+"/net/dev");
      try {
          if (proc.waitFor() != 0) {
              System.err.println("exit value = " + proc.exitValue());
              //JOptionPane.showMessageDialog(new JFrame(), "哥们抱歉,好像出问题了!关掉重试吧!");
          }
          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("wlan0:"),str1.indexOf("wlan0:")+90);
     //接收字节:
      String str4=str2.substring(7,16);
      str4 = str4.trim();
      int b=Integer.parseInt(str4);
      str3=b/1024;
      //System.out.println(str3);
      } catch (InterruptedException e) {
          System.err.println(e);
      }finally{
          try {
              proc.destroy();
          } catch (Exception e2) {
          }
      }
  }
      catch (Exception StringIndexOutOfBoundsException)
      {
          //System.out.print("请检查设备是否连接");

      }   

      return str3;
}


流量取值:

adb shell cat /proc/Pid/net/dev
public static double GetFlow(String PackageName) throws IOException {
          double str3=0;
          String Pid=PID(PackageName);
      try{
          Runtime runtime = Runtime.getRuntime();
       /*   Process proc2 = runtime.exec("");*/
          Process proc = runtime.exec("adb shell cat /proc/"+Pid+"/net/dev");
          try {
              if (proc.waitFor() != 0) {
                  System.err.println("exit value = " + proc.exitValue());
                  //JOptionPane.showMessageDialog(new JFrame(), "哥们抱歉,好像出问题了!关掉重试吧!");
              }
              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("wlan0:"),str1.indexOf("wlan0:")+90);
         //接收字节:
          String str4=str2.substring(7,16);
          str4 = str4.trim();
          int b=Integer.parseInt(str4);
          str3=b/1024;
          //System.out.println(str3);
          } catch (InterruptedException e) {
              System.err.println(e);
          }finally{
              try {
                  proc.destroy();
              } catch (Exception e2) {
              }
          }
      }
          catch (Exception StringIndexOutOfBoundsException)
          {
              //System.out.print("请检查设备是否连接");

          }   

          return str3;
    }

取到流量后可以用步骤后的流量减去步骤前的流量得到步骤消耗流量!也可以用时间差来计算!

电量取值:

adb shell dumpsys battery

这里只是剩余电量!


public static double battery() throws IOException {
      double batt=0;
      Runtime runtime = Runtime.getRuntime();
      Process proc = runtime.exec("adb shell dumpsys battery");
      String str3;
      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("level"),str1.indexOf("level")+10);
      str3=str2.substring(6,10);
      str3.trim();
      batt=Double.parseDouble(str3);
      } catch (InterruptedException e) {
          System.err.println(e);
      }finally{
          try {
              proc.destroy();
          } catch (Exception e2) {
          }
      }

      return batt;

}


使用说明

第一步:先检查设备是否连接。

adb devices

第二步:把被测程序打开。

第三步:输入包名点击开始。

查包名的方法 (列出所有的包名):

adb  shell  ps

工具展示

日志的收集放在 D:/log

Monkey

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

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

还是很实用的,赞一个

第二篇 没有第一篇给力啊。 再修改修改,放上关键性代码分析。 @testly

#2 楼 @lihuazhang 只是一个工具分享,没啥特别的!

赞,简单实用就是极好的

嗯,第二篇略没有高潮。。。

我是 Windows7 32 位的系统。不兼容吗?不能使用

#7 楼 @alice 额,留个邮箱,我单独帮你生成一个 32 位的

还是等你开源源码吧。

testly #10 · 2015年05月18日 Author

#9 楼 @doctorq 我在弄 GitHub 了

windows7 64,启动测试没反应,monkey 测试提示出错

你这个电量获取是通过 usb 连接的吗?会有影响吧?充放电。

testly #13 · 2015年05月18日 Author

#11 楼 @x746560359 你自己用命令跑一下试试

usb 充电问题如何解决?是否可以做个 app 在同一 wifi 网络下传输到 pc 端展示数据(此监控 app 保持稳定)

一下载就提示网络错误。。。

#8 楼 @testly 赞,同求 Win7-32 位版本的工具,谢谢!

testly #30 · 2015年05月19日 Author

#16 楼 @laiyuncong8404 已更新了,看上面!

支持 mac 吗 楼主?

@testly 同求 win7-32~~~

testly #20 · 2015年05月19日 Author

#19 楼 @felixtest 上面已经更新了!

testly #21 · 2015年05月19日 Author

#18 楼 @steavenhuang mac 版 我还没发布!!哈哈

@testly 请问你的启动时间是指 activity 的启动时间还是应用的启动时间,启动时间是通过 logcat 来获得,然后 grep ActivtyManager?

testly #10 · 2015年05月19日 Author

#23 楼 @app_testing 我的就是启动 main 函数的时间

@testly 能开源不?

testly #26 · 2015年05月20日 Author

#25 楼 @app_testing 必须可以啊

能回复下 12 楼吗?

testly #37 · 2015年05月20日 Author

#12 楼 @gaoxing200851 不好意思啊,我没看到你的问题,抱歉 !
我这里的电流指的是剩余电量呢,亲,所以没有关系的,如果亲要知道耗电量的话,后面我会发帖说明的!

109楼 已删除

期待看到 mac 的开源版本啊

mac 可以联系我帮你内测

如果插着 usb 测试的话,因为会不断的充电,获取剩余的测试意义是什么呢?

jdk1.6 配置后仍然提示设置 exe4j_java_home 目录,已经找了许多资料仍未解决,请问怎么解决呢?

testly #34 · 2015年05月20日 Author

#32 楼 @gaoxing200851 你说的充电 问题导致剩余电量不变的问题涉及到功耗增减的问题!如果你硬要纠结,可以用 adbwireless 无线获取系统资源可以实现不连接数据线获取系统资源

testly #35 · 2015年05月20日 Author

#33 楼 @jiguanghover 什么报错?发出来

已经解决了,需要安装 jre1.7 的环境,而不是 jre1.6 的环境,jdk1.6 会提示错误 no JVM could be found on your system.Please define EXE4J_JAVA_HOME

@testly @jiguanghover 即使使用无线获取的话,电量的消耗也有其他 app 的消耗,以及屏幕的点亮会消耗电量,感觉还是不够准确的

@app_testing @testly 电量数据读取 processAPPusage() 是否更好一些? 另外 android 由于本身基础系统、wif 等其他因素影响。得到的只能是相对值,不可能是绝对值。测试可以关注 1 使用电量的稳定 2 对比同类型产品不能出现耗电量太大的弱点。之前说想用 wifi 来出来数据连接,只是担心充电会导致影响电量相关数据的获取。

非常不错,坐等源码 研究研究。

请教下:
1、流程是不是用 adb shell 命令把需要监控的数据获取,然后通过 java 代码过滤处理,这些数据是保存在哪里?直接保存到一个 txt 文件,然后再用图表插件处理出来吗?
2、java 代码是在 PC 端运行吗?具体没看懂怎么运作的?

testly #42 · 2015年05月25日 Author

#41 楼 @tavisdxh 直接截取后转 double 直接传 JFreeChart 制表

你的 pid 是怎么处理出来的呢?

testly #44 · 2015年05月25日 Author

#43 楼 @gaoxing200851 adb shell ps 都要去调一次作为变量传过来

git 上面还没有共享,坐等分享,好好研究下

为啥输入包名,没法测试,总是提示我未链接或者包名错误,我用的 64 位机,而且我用了 adb 命令都 ok,环境变量配置也 ok,看了一下,报名也对的,直接用 top 变量也可以的,为啥 winform 检测不到包名

testly #47 · 2015年05月26日 Author

#46 楼 @adobe123 什么手机?root 了吗?

我也是 32 位的电脑,手机已经 root 了。但是总是未链接或者包名错误。能给源码吗?我是 oppo 手机。

testly #49 · 2015年05月27日 Author

嗯嗯、源码我会传上来这几天

很不错的工具

没有 D 盘伤不起。。。

testly #52 · 2015年06月03日 Author

#51 楼 @jacky 改下就可以了

你这个启动时间获取怎么算的

@testly 启动时间的运算逻辑

testly #62 · 2015年06月03日 Author

#54 楼 @dingx010602 调 adb shell start am 调 启动函数

为什么取消分享了啊

testly #57 · 2015年06月05日 Author

#56 楼 @ppcwhy 再看看

D 盘没有 log 这个文件夹 怎么回事 楼主

testly #59 · 2015年06月08日 Author

#58 楼 @addison 这是个 bug,先手工建立一个吧!

多谢楼主 解决了 自己手动创建个文件夹就可以了。。。


包名也正确 adb 端口也有。就是连接不上

#62 楼 @xiaome 对有的包名好像支持不是很好呢 我刚开始也出那个问题,后来换另外一个包名好用

话说这个根本停不下来么?我点击开始测试就一直在测试,然后右上角也关不掉,只能杀进程

那个 monkey 为什么点击后总是运行不起来了,是不是需要做什么特殊的配置呢

@testly 可以给些帮助吗

testly #67 · 2015年10月14日 Author

#65 楼 @cary_zhang 具体是什么情况呢?用命令执行是好的么

用上啦,日志中没有打印电量是故意的吗?
CpuChart.java

public static void log() throws IOException, InterruptedException
 {
     if (Menu.log=="1")
     {
            Outlog.log.writelogs("D:/log/Monitor_log",time,"时间: "+time1+"  Cpu:"+GetTop.cpu(Menu.text)+"%"+"               Memory: "+HeapChart.randomNum()/1024+"MB"+"                流量:"+FlowChart.randomNum()+"Kb");
     }
     }

BatteryChart.java

private double randomNum() throws IOException  
 {     

     System.out.println(Getbattery.battery());        
     return Getbattery.battery();  
 }  

#62 楼 @xiaome 我也遇到这样的情况 请问你这个问题解决了吗

testly #70 · 2015年12月09日 Author

#69 楼 @subona
换个手机试试,或者把源码拉出来自己调试一下看哪里错了

testly #71 · 2015年12月09日 Author

#68 楼 @yuweixx 是的,你可以加上

监控的实时 cpu、内存、流量的信息 能统计一段时间的吗 需要怎么修改

testly #73 · 2015年12月10日 Author

#72 楼 @long 打上时间戳 开始和结束时间,判断结束时间减去开始时间为多少分钟后停止

#70 楼 @testly 用你的源码调试 OK 了 ,就是 Flow 图一直没动静 时间也不更新,还在查原因

数据的截取用 split(“\s+”)比用 subString 好得多,感觉有些 bug 就是出在取数据的问题上,小小建议_^

#76 楼 @testly 你好,我在取值 cpu 的时候,用的语句是 top -d 1|grep +PackageName 在你的 top -n 的时候只能获取到一行值。不知道是否有什么区别。希望可以给点指导,谢谢

@xiaome 我这边出现的情况和你的一样。
@testly 有新版本了吗?

@testly monkey 一直提示失败重试,有什么解决办法?

testly #80 · 2016年04月15日 Author

#79 楼 @qa8335351 检查包名然后其他的都不要填

mac 电脑 可以帮忙生成一个 dmg 么。。。

期待 mac 版

@testly 请问一下用 dumpsys cpuinfo 和用 top 取 CPU 信息有什么区别么

是用的 monkey 压测吧?如果是,这样统计 cpu,内存是否有意义?

testly #85 · 2016年05月14日 Author

#83 楼 @itboyst 我的理解是 一个是类似进程管理器的实际使用占比,一个单核是 cpu 占比吧因为有时候可以超过 100%

testly #86 · 2016年05月16日 Author

#84 楼 @lose 第一这个不是专门搞什么压测的,主要是用来采集数据来做分析的,
第二有无意义是根据你公司对应的业务场景来的,

你好,请问下,这个工具源码在 git 上的地址是?自己想二次开发下

电脑没有 D 盘日志会写到哪里?

testly #89 · 2016年08月05日 Author

#88 楼 @eyesee_janno

不好意思哈,暂时比较简陋
接下来会开发一个新版的,到时候 log 可以自定义路径,还加了 很多其他的新功能

@testly 楼主你好,你提供的这些方法,我在运行的过程中获取到的字符串都是 “” 呢,为什么?

testly #91 · 2016年08月18日 Author

#90 楼 @mild_amy 可能字符串截取出问题了,这很早以前写的,截取的方式是有问题的

我这边上无法使用,启动出现错误;java.lang.UnsupportedClassVersionError: Monitor/Menu : Unsupported major.minor version 51.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$000(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at com.exe4j.runtime.LauncherEngine.launch(Unknown Source)
at com.exe4j.runtime.WinLauncher.main(Unknown Source)

@testly 楼主,代码在 github 的链接地址在哪?代码开源了吗?

楼主,能弄一个 mac 版本的么

win7 64 位 monkey 用不了

win7 64 位 monkey 用不了

win7 64 位 monkey 用不了 1

win7 64 位 monkey 用不了 1

@testly 你好,这个项目的 github 地址是多少呀?

大神有 mac 版的吗?

testly #103 · 2017年03月01日 Author
joker 回复

近期开放出来

testly #103 · 2017年03月01日 Author
绝影 回复

谢谢反馈

获取内存和获取流量的代码重复了~@testly

首先特别感谢大神楼主的分享
不过还是想问您些问题,我的是 win64 系统, 然后在运行这个工具的时候出现了时间轴上的时间重合的问题,还出现了一个错误报告,也只能关闭进程关闭工具

您有时间能看一下么

楼主,文中提到的链接打不开,方便提供下这个工具吗?(win7-32)

匿名 在 android 性能监控工具介绍 (Python+PyQt 实现) 中提及了此贴 11月23日 20:15

楼主,有 mac 版的吗?

testly #109 · 2018年06月26日 Author
tester_newbee 回复

有 mac 版 过段时间开放吧


地址打不开,超时

淘宝云盘都关闭了,楼主有新链接吗?

有最新的可以用的吗?

楼主你好,不知道你还看这个帖子吗,你上面的链接不能用了,请问还有更新吗,我想学习一下

仅楼主可见
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册