Android自动化性能收集

Android自动化性能收集

Android 功能测试自动化框架较多,UIAutomator,Robotium,Appium等。Case执行过程中,可能希望收集手机的性能指标,包括内存、cpu、流量等。使用java+shell+bat简单实现了android手机性能收集。

简述

过程很简单:

  • 在启动自动化case前,执行收集信息的命令。
    其实就是一些adb shell命令,如下:

          adb shell top -n 1| awk ‘{print $3" "$10}‘ >> cpu.dat
          adb shell ps | awk ‘{print $5" "$9}‘ >> mem.dat  
    
          //android sdk level 大于16
          adb shell cat /proc/uid_stat/$uid/tcp_rcv >> $uid"_recv.dat"
          adb shell cat /proc/uid_stat/$uid/tcp_snd >> $uid"_snd.dat"  
    
          //android sdk level 小于16
          adb shell cat /proc/$pid/net/dev | grep wlan | awk ‘{print $2" "$10}‘ >> $pid"_net.dat"
    
  • 执行自动化case,可能需要很久。这个过程中,上面的命令在不断地执行
  • case执行结束,kill掉第一步中的命令
  • 分析收集到的dat文件,使用jscharts绘出走势图

脚本

cpu

使用top命令不断查看各进程的cpu占用

linux

get-android-cpu.sh

    #!/bin/sh

    #path--target/android-info/mem/dat
    cd ../../../
    mkdir -p target/android-info/cpu/dat
    mkdir -p target/android-info/cpu/html

    cp src/main/resources/jscharts.js target/android-info/cpu/html
    cd target/android-info/cpu/dat

    while true
    do
        adb shell top -n 1| awk ‘{print $3" "$10}‘ >> cpu.dat
        sleep 15
    done

windows

get-android-cpu.bat

    cd ..\..\jenkins\workspace\android-info-end3
    mkdir target\android-info\cpu\dat
    mkdir target\android-info\cpu\html

    copy src\main\resources\jscharts.js target\android-info\cpu\html
    cd target\android-info\cpu\dat

    :run
        adb shell top -n 1 | awk "{print $3\" \"$10}" >> cpu.dat
        ping 127.0.0.1 -n 15 > null
    goto run

memory

使用ps命令不断查看各进程的内存占用

linux

get-android-mem.sh

    #!/bin/sh

    #path--target/android-info/mem/dat
    cd ../../../
    mkdir -p target/android-info/mem/dat
    mkdir -p target/android-info/mem/html
    cp src/main/resources/jscharts.js target/android-info/mem/html
    cd target/android-info/mem/dat

    while true
    do
        adb shell ps | awk ‘{print $5" "$9}‘ >> mem.dat
        sleep 15
    done

windows

    cd ..\..\jenkins\workspace\android-info-end3
    mkdir target\android-info\mem\dat
    mkdir target\android-info\mem\html
    copy src\main\resources\jscharts.js target\android-info\mem\html

    cd target\android-info\mem\dat

    :run
        adb shell ps | awk "{print $5\" \"$9}" >> mem.dat
        ping 127.0.0.1 -n 15 > null
    goto run

流量

android 4.0以上版本可以用/proc/uid_stat/$uid/tcp_rcv/proc/uid_stat/$uid/tcp_snd来获取某个程序的上下行流量;而4.0以下版本要用cat /proc/$pid/net/dev来查看上下行流量。uid和pid的关系,可以从/data/system/packages.list这个文件中获取。

linux

判断android api level:

    #!/bin/sh
    #android 4.0以上和4.0以下方法不同
    #get android sdk level
    apileveltemp=`adb shell getprop | grep ro.build.version.sdk`
    apilevel=${apileveltemp:25:2}
    chmod +x *.sh

    echo "android api level:"$apilevel
    if [ $apilevel -gt 14 ]
    then
        ./get-android-net-gt-4.0.sh
    elif [ $apilevel -lt 14 ]
    then
        ./get-android-net-lt-4.0.sh
    fi

get-android-net-gt-4.0.sh

    #!/bin/sh

    #android api level great than 14(android 4.0)
    #path--target/android-info/net/dat
    cd ../../../
    mkdir -p target/android-info/net/dat
    mkdir -p target/android-info/net/html
    cp src/main/resources/jscharts.js target/android-info/net/html
    cd target/android-info/net/dat

    cd ..
    echo "adb pull/data/system/packages.list--start"
    adb pull /data/system/packages.list
    cd dat

    while true
    do

        echo "get net info from /proc/uid-stat/$uid"
        for i in `adb shell ls /proc/uid_stat`
        do
            #delete the Enter character
            uid=`echo $i | tr -d ["\r\n"]`
            adb shell cat /proc/uid_stat/$uid/tcp_rcv >> $uid"_recv.dat"
            adb shell cat /proc/uid_stat/$uid/tcp_snd >> $uid"_snd.dat"
        done
        sleep 15
    done

get-android-net-lt-4.0.sh

    #!/bin/sh

    #path--target/android-info/net/dat
    cd ../../../
    mkdir -p target/android-info/net/dat
    mkdir -p target/android-info/net/html
    cp src/main/resources/jscharts.js target/android-info/net/html
    cd target/android-info/net/dat

    #get /proc/$pid/net/dev
    while true
    do
        #get pid
        for i in `adb shell ps | awk ‘{print $2}‘`
        do
            pid=`echo $i | tr -d ["\r\n"]`
            echo $pid
            adb shell cat /proc/$pid/net/dev | grep wlan | awk ‘{print $2" "$10}‘ >> $pid"_net.dat"
        done

        sleep 15
    done

windows

bat命令不熟,不知道如何在windows下实现linux下地反转义,这里用java代码实现。

    import java.io.*;

    /**
     * Created by Xuemeng Wang on 14-9-15.
     * api Level > 16
     */
    public class GetNetInfo {
        public static void main(String[] args) {

            String uidString = execCmd("adb shell ls /proc/uid_stat");
            String[] uidArray = uidString.split("\n");
            int length = uidArray.length-1;
            for(int i=0;i<=length-1;i++)
            {
                String contentRcv = execCmd("adb shell cat /proc/uid_stat/"+uidArray[i]+"/tcp_rcv");
                String contentSnd = execCmd("adb shell cat /proc/uid_stat/"+uidArray[i]+"/tcp_snd");
                System.out.println(System.getProperty("user.dir"));
                try {
                    File file = new File(uidArray[i]+"_recv.dat");
                    if(!file.exists()) file.createNewFile();

                    File file2 = new File(uidArray[i]+"_snd.dat");
                    if(!file2.exists()) file2.createNewFile();

                    FileWriter fileWriter1 = new FileWriter(file, true);
                    FileWriter fileWriter2 = new FileWriter(file2, true);
                    fileWriter1.write(contentRcv);
                    fileWriter2.write(contentSnd);
                    fileWriter1.close();
                    fileWriter2.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        public static String execCmd(String command)
        {
            BufferedReader br = null;
            StringBuffer stringBuffer = new StringBuffer();
            try {
                Process p = Runtime.getRuntime().exec(command);
                br = new BufferedReader(new InputStreamReader(p.getInputStream()));
                String line = null;
                while ((line = br.readLine()) != null) {
                if("".equals(line.trim())) continue;

                    stringBuffer.append(line+"\n");
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {

                if (br != null) {
                    try {
                        br.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            return stringBuffer.toString();
        }
    }

api level小于16的情况,我没用到,略掉:)。

杀掉进程

linux: ps -ef | grep get-android- | grep -v grep | awk ‘{print $2}‘ | xargs kill -9
windows(后台运行,其实是cmd进程,注意下面会杀掉所有的cmd进程):

    taskkill /F /IM cmd.exe
    taskkill /F /IM adb.exe

结果收集

使用java分析dat,给出分析cpu的代码,工程已上传到github,https://github.com/yeetrack/android-performance

CpuInfo.java

    package com.meilishuo.android.performance;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.testng.annotations.Test;

    import java.io.*;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import java.util.TreeMap;

    /**
     * Created by victor on 14-9-9.
    */
    public class CpuInfo {
        private static final Logger logger = LoggerFactory.getLogger(MemInfo.class);
        private static final String JSCHARTPATH = "target/android-info/cpu/html/";
        private static final String MEMFILEPATH = "target/android-info/cpu/dat/cpu.dat";

        TreeMap<String, List<String>> cpuMap = new TreeMap<String, List<String>>();

        /**
        * 解析cpu.dat存储到map中
        */
        public void parseCpuFile()
        {
            File file = new File(MEMFILEPATH);
            if(null==file) return;

            try {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
                String line = null;

                while((line=bufferedReader.readLine())!=null)
                {
                    String[] array = line.trim().split(" "); //空格分隔
                    if(null==array || array.length!=2 || !array[0].contains("%") || "".equals(array[1]) || "Name".equals(array[1]))
                        continue;
                    if(cpuMap.size()==0 || !cpuMap.containsKey(array[1]))
                    {
                        List<String> memList = new ArrayList<String>();
                        memList.add(array[0].substring(0, array[0].indexOf("%")));
                        cpuMap.put(array[1], memList);
                    }
                    else
                    {
                        cpuMap.get(array[1]).add(array[0].substring(0, array[0].indexOf("%")));
                    }
                }
                System.out.println(cpuMap.size());
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        /**
        * 将map中的数据写到到xml中
        */
        public void writeXmlFromMap()
        {
            if(null==cpuMap || cpuMap.size()==0)
                return;
            Iterator<String> it = cpuMap.keySet().iterator();
            while(it.hasNext())
            {
                String key = it.next();
                List<String> value = cpuMap.get(key);
                if(null==value || value.size()<=1)
                    continue;
                //写入xml
                File file = new File(JSCHARTPATH+key.replace("/", "_").replace(":", "_")+"_cpu.xml");
                try {
                    BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true)));
                    bufferedWriter.write(
                    "<?xml version=\"1.0\"?>\n" +
                            "<JSChart>\n" +
                            "\t<dataset type=\"line\">");
                    int pos = 1;
                    for(String index : value)
                    {
                        bufferedWriter.write("<data unit=\""+pos+"\" value=\""+index+"\"/>\n");
                        pos++;
                    }
                    bufferedWriter.write(
                    "</dataset>\n" +
                            "\t<optionset>\n" +
                            "\t\t<option set=\"setLineColor\" value=\"‘#8D9386‘\"/>\n" +
                            "\t\t<option set=\"setLineWidth\" value=\"4\"/>\n" +
                            "\t\t<option set=\"setTitleColor\" value=\"‘#7D7D7D‘\"/>\n" +
                            "\t\t<option set=\"setAxisColor\" value=\"‘#9F0505‘\"/>\n" +
                            "\t\t<option set=\"setGridColor\" value=\"‘#a4a4a4‘\"/>\n" +
                            "\t\t<option set=\"setAxisValuesColor\" value=\"‘#333639‘\"/>\n" +
                            "\t\t<option set=\"setAxisNameColor\" value=\"‘#333639‘\"/>\n" +
                            "\t\t<option set=\"setTextPaddingLeft\" value=\"0\"/>\n" +
                            "\t</optionset>\n " +
                            "</JSChart>");
                    bufferedWriter.flush();
                    bufferedWriter.close();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        /**
        * 生成jschart html文件
        */
        public void writeJsHtml()
        {
            File file = new File(JSCHARTPATH);
            File[] xmlFiles = file.listFiles(new FileFilter() {
                @Override
                public boolean accept(File pathname) {
                    return pathname.getName().endsWith("_cpu.xml");
                }
            });
            if(null== xmlFiles || xmlFiles.length==0) return;
            for(File index : xmlFiles)
            {
                File htmlFile = new File(index.getAbsolutePath().replace(".xml", ".html"));
                try {
                    BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(htmlFile));

继续阅读->

时间: 2024-10-13 05:40:17

Android自动化性能收集的相关文章

Android界面性能调优手册

转载:https://androidtest.org/android-graphics-performance-pattens/#11 界面是 Android 应用中直接影响用户体验最关键的部分.如果代码实现得不好,界面容易发生卡顿且导致应用占用大量内存. 我司这类做 ROM 的公司更不一样,预装的应用一定要非常流畅,这样给客户或用户的第一感觉就是快.又卡又慢的应用体验,会影响客户或用户对产品的信心和评价,所以不可忽视. 目录 一. Android渲染知识 1.1 绘制原理 1.2 掉帧 1.3

Android内存性能优化(内部资料总结)

刚入门的童鞋肯能都会有一个疑问,Java不是有虚拟机了么,内存会自动化管理,我们就不必要手动的释放资源了,反正系统会给我们完成.其实Java中没有指针的概念,但是指针的使用方式依然存在,一味的依赖系统的gc,很容易就造成了内存的浪费.   Java基于垃圾回收的内存机制 Java的内存管理机制会自动回收无用对象所占用的内存,减轻手工管理内存的负担 1.C/C++: 从申请.使用.释放都需要手工管理 2.Java:无用的对象的内存会被自动回收 什么样的对象是无用的对象 1.Java通过引用来操作一

Android客户端性能优化(魅族资深工程师毫无保留奉献)

本文由魅族科技有限公司资深Android开发工程师degao(嵌入式企鹅圈原创团队成员)撰写,是degao在嵌入式企鹅圈发表的第一篇原创文章,毫无保留地总结分享其在领导魅族多个项目开发中的Android客户端性能优化经验,极具实践价值! 即日起,嵌入式企鹅圈将在之前五个专栏(Linux内核驱动情景分析.资源紧缺型SOC嵌入式架构设计.嵌入式交叉工具链及其应用.嵌入式设计和编程.微信硬件平台和物联网解决方案)新增Android开发专栏!更多Android.Linux.嵌入式和物联网原创技术分享敬请

Android基础性能检测与分析

本文内容:基于Android基础性能检测与分析 版权声明:本文为原创文章,未经允许不得转载 博客地址:http://blog.csdn.net/kevindgk 前言 UI性能分析 应用启动时间计算以及程序启动白屏问题 内存分析 内存优化原则 内存区分 内存分析 内存泄露工具MAT 内存泄露工具LeakCanary 耗电量分析 性能检测和分析工具 1 高通性能分析器 - TrepnProfiler 2 高通调试器 - TuneUpKit 3 阿里-易测 云测平台 引用 联系方式 前言 最近一段时

Android内存性能优化(内部资料总结) eoe转载

刚入门的童鞋肯能都会有一个疑问,Java不是有虚拟机了么,内存会自动化管理,我们就不必要手动的释放资源了,反正系统会给我们完成.其实Java中没有指针的概念,但是指针的使用方式依然存在,一味的依赖系统的gc,很容易就造成了内存的浪费. Java基于垃圾回收的内存机制 Java的内存管理机制会自动回收无用对象所占用的内存,减轻手工管理内存的负担 1.C/C++: 从申请.使用.释放都需要手工管理 2.Java:无用的对象的内存会被自动回收 什么样的对象是无用的对象 1.Java通过引用来操作一个具

Android APP 性能优化的一些思考

说到 Android 系统手机,大部分人的印象是用了一段时间就变得有点卡顿,有些程序在运行期间莫名其妙的出现崩溃,打开系统文件夹一看,发现多了很多文件,然后用手机管家 APP 不断地进行清理优化 ,才感觉运行速度稍微提高了点,就算手机在各种性能跑分软件面前分数遥遥领先,还是感觉无论有多大的内存空间都远远不够用.相信每个使用 Android 系统的用户都有过以上类似经历,确实,Android 系统在流畅性方面不如 IOS 系统,为何呢,明明在看手机硬件配置上时,Android 设备都不会输于 IO

Android app 性能优化的思考--性能卡顿不好的原因在哪?

说到 Android 系统手机,大部分人的印象是用了一段时间就变得有点卡顿,有些程序在运行期间莫名其妙的出现崩溃,打开系统文件夹一看,发现多了很多文件,然后用手机管家 APP 不断地进行清理优化 ,才感觉运行速度稍微提高了点,就算手机在各种性能跑分软件面前分数遥遥领先,还是感觉无论有多大的内存空间都远远不够用.相信每个使用 Android 系统的用户都有过以上类似经历,确实,Android 系统在流畅性方面不如 IOS 系统,为何呢,明明在看手机硬件配置上时,Android 设备都不会输于 IO

十大技巧优化Android App性能

无论锤子还是茄子手机的不断冒出,Android系统的手机市场占有率目前来说还是最大的,因此基于Android开发的App数量也是很庞大的.那么,如何能开发出更高性能的Android App?相信是软件开发公司以及广大程序员们头疼的一大难题.今天,就给大家提供几个提高Android App性能的技巧. 高效地利用线程 1.在后台取消一些线程中的动作 我们知道App运行过程中所有的操作都默认在主线程(UI线程)中进行的,这样App的响应速度就会受到影响.会导致程序陷入卡顿.死掉甚至会发生系统错误.

【读书笔记】《Android应用性能优化最佳实践》

<第一行代码>读书笔记 一.引言 二.读书内容 书名:<Android应用性能优化最佳实践> 作者:罗彧成 (腾讯音乐Android开发总监) 出版社:机械工业出版社 封面: 三.书籍评价 四.个人心得 五.参考文档