版本号 V 1.1.0

Android性能测试分为两类:
1、一类为rom版本(系统)的性能测试
2、一类为应用app的性能测试(本次主要关注点为app的性能测试)

Android的app性能测试包括的测试项比如:

内存、adb shell dumpsys meminfo com.xxxxx.xxxx | findstr TOTAL

CPU、adb shell dumpsys cpuinfo | findstr com.xxxxx.xxxx

流量、adb shell ps | grep com.xxxxx.xxxx、获取进程使用的流量:adb shell cat /proc/"+pid+"/net/dev

功耗、adb shell dumpsys battery

GPU、adb shell dumpsys gfxinfo com.xxxxx.xxxx

1、内存

本次测试以xxxxxxapp为测试对象。配合monkey测试随机事件1000次、忽略超时、忽略崩溃

命令: monkey -p com.xxxxx.xxxx --throttle 500 --ignore-timeouts --ignore-crashes   --monitor-native-crashes -v -v -v 1000

shell命令:adb shell dumpsys meminfo com.xxxxx.xxxx | findstr TOTAL

思路:在运行monkey的过程中 每隔一段时间去取内存的数据

代码demo

# coding:utf-8

import os
import time
import matplotlib
from matplotlib import pyplot as plt data2 = []
def getmeminfo():
# cmd = "adb shell monkey -p com.xxxxx.xxxx --throttle 500 --ignore-timeouts --ignore-crashes --monitor-native-crashes -v -v -v 1000"
# os.popen(cmd)
print("*"*20)
for i in range(10):
cmd = (
"adb shell dumpsys meminfo com.xxxxx.xxxx | findstr TOTAL >>E:\mem.txt"
)
os.popen(cmd)
time.sleep(2)
with open("E:\mem.txt", "r") as f:
lines = f.readlines()
for i in range(0, len(lines), 2):
data2.append(int(lines[i].split()[1])) def drawlabe(data1, data2):
#mainColor = (42 / 256, 87 / 256, 141 / 256, 1)
plt.xlabel("次数")
plt.ylabel("内存kb")
plt.plot(data1, data2, marker="*")
plt.title("内存波动折线图")
plt.show() if __name__ == "__main__":
number = getmeminfo()
print(data2)
data1 = [1,2,3,4,5,6,7,8,9,10]
drawlabe(data1, data2)

拓展:

  1. 内存测试中的测试子项:
    1)空闲状态下的应用内存消耗情况
    2)中等规格状态下的应用内存消耗情况
    3)满规格状态下的应用内存消耗情况
    4)应用内存峰值情况
    5)应用内存泄露情况
    6)应用是否常驻内存
    7)压力测试后的内存使用情况

  2. 内存问题现象:
    1)内存抖动
    2)大内存对象被分配
    3)内存不断增长
    4)频繁GC

  3. 内存数据获取:
    1、各种linux命令(top、free、meminfo…)
    2、通过dumpsys
    adb shell dumpsys meminfo [pakagename | pid]

2、CPU

本次测试以xxxxxxapp为测试对象。配合monkey测试随机事件1000次、忽略超时、忽略崩溃

命令: monkey -p com.xxxxx.xxxx --throttle 500 --ignore-timeouts --ignore-crashes   --monitor-native-crashes -v -v -v 1000

shell命令:adb shell dumpsys cpuinfo | findstr com.xxxxx.xxxx

demo代码:

#/usr/bin/python
#encoding:utf-8
import csv
import os
import time
#控制类
class Controller(object):
def __init__(self, count):
self.counter = count
self.alldata = [("timestamp", "cpustatus")]
#单次测试过程
def testprocess(self):
result = os.popen("adb shell dumpsys cpuinfo | findstr com.xxxxx.xxxx")
for line in result.readlines():
cpuvalue = line.split("%")[0]
currenttime = self.getCurrentTime()
self.alldata.append((currenttime, cpuvalue))
#多次执行测试过程
def run(self):
while self.counter >0:
self.testprocess()
self.counter = self.counter - 1
time.sleep(3)
#获取当前的时间戳
def getCurrentTime(self):
currentTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
return currentTime
#数据的存储
def SaveDataToCSV(self):
csvfile = file('cpustatus.csv', 'wb')
writer = csv.writer(csvfile)
writer.writerows(self.alldata)
csvfile.close()
if __name__ == "__main__":
controller = Controller(10)
controller.run()
controller.SaveDataToCSV()

拓展:

  1. CPU测试中的测试子项:
    1)空闲状态下的应用CPU消耗情况
    2)中等规格状态下的应用CPU消耗情况
    3)满规格状态下的应用CPU消耗情况
    4)应用CPU峰值情况

  2. CPU数据获取:
    1)adb shell dumpsys cpuinfo | grep packagename
    2)top命令
    adb shell top -m 10 -s cpu #查看占用cpu最高的前10个程序(-t 显示进程名称,-s 按指定行排序,-n 在退出前刷新几次,-d 刷新间隔,-m 显示最大数量)
    adb shell top | grep PackageName > /address/cpu.txt

3 流量篇

shell命令:adb shell ps | grep com.xxxxx.xxxx

  1. 概念:
    中等负荷:应用正常操作
    高负荷:应用极限操作

  2. demo代码:

    #/usr/bin/python
    #encoding:utf-8
    import csv
    import os
    import string
    import time
    #控制类
    class Controller(object):
    def __init__(self, count):
    #定义测试的次数
    self.counter = count
    #定义收集数据的数组
    self.alldata = [("timestamp", "traffic")]
    #单次测试过程
    def testprocess(self):
    #执行获取进程的命令
    result = os.popen("adb shell ps | grep com.xxxxx.xxxx")
    #获取进程ID
    pid = result.readlines()[0].split(" ")[5]
    #获取进程ID使用的流量
    traffic = os.popen("adb shell cat /proc/"+pid+"/net/dev")
    for line in traffic:
    if "eth0" in line:
    #将所有空行换成#
    line = "#".join(line.split())
    #按#号拆分,获取收到和发出的流量
    receive = line.split("#")[1]
    transmit = line.split("#")[9]
    elif "eth1" in line:
    # 将所有空行换成#
    line = "#".join(line.split())
    # 按#号拆分,获取收到和发出的流量
    receive2 = line.split("#")[1]
    transmit2 = line.split("#")[9]
    #计算所有流量的之和
    alltraffic = string .atoi(receive) + string .atoi(transmit) + string .atoi(receive2) + string .atoi(transmit2)
    #按KB计算流量值
    alltraffic = alltraffic/1024
    #获取当前时间
    currenttime = self.getCurrentTime()
    #将获取到的数据存到数组中
    self.alldata.append((currenttime, alltraffic))
    #多次测试过程控制
    def run(self):
    while self.counter >0:
    self.testprocess()
    self.counter = self.counter - 1
    #每5秒钟采集一次数据
    time.sleep(5)
    #获取当前的时间戳
    def getCurrentTime(self):
    currentTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    return currentTime
    #数据的存储
    def SaveDataToCSV(self):
    csvfile = file('traffic.csv', 'wb')
    writer = csv.writer(csvfile)
    writer.writerows(self.alldata)
    csvfile.close()
    if __name__ == "__main__":
    controller = Controller(5)
    controller.run()
    controller.SaveDataToCSV()

拓展:

  1. 流量测试中的测试子项:
    1、应用首次启动流量值
    2、应用后台连续运行 2 小时的流量值
    3、应用高负荷运行的流量峰值
    4、应用中等负荷运行时的流量均值

  2. 获取流量数据:
    1、tcpdump+wireshark
    2、/proc/net/目录下相关文件
    cat /proc/net/dev 获取系统的流量信息
    3、查询应用的pid: adb shell ps | grep tataufo #如:31002
    通过PID获取该应用的流量数据: adb shell cat /proc/31002/net/dev
    (wlan0代表wifi上传下载量标识, 单位是字节可以/1024换算成KB, 打开手机飞行模式再关掉就可以将wlan0中的值初始化0)
    4、查询应用的pid: adb shell ps | grep tataufo #如:31002
    通过PID获取UID:adb shell cat /proc//status
    通过UID获取:adb shell cat /proc/net/xt_qtaguid/stats | grep 31002
    5、通过adb shell dumpsys package来获取应用的uid信息,然后在未操作应用之前,通过查看 :
    adb shell cat /proc/uid_stat/uid/tcp_rcv
    adb shell cat /proc/uid_stat/uid/tcp_snd
    获取到应用的起始的接收及发送的流量,然后我们再操作应用,再次通过上述2条命令可以获取到应用的结束的接收及发送的流量,通过相减及得到应用的整体流量消耗
    6、Android代码:Android的TrafficStats类

4 功耗篇

shell命令:adb shell dumpsys battery

demo代码:

#/usr/bin/python
#encoding:utf-8
import csv
import os
import time
#控制类
class Controller(object):
def __init__(self, count):
#定义测试的次数
self.counter = count
#定义收集数据的数组
self.alldata = [("timestamp", "power")]
#单次测试过程
def testprocess(self):
#执行获取电量的命令
result = os.popen("adb shell dumpsys battery")
#获取电量的level
for line in result:
if "level" in line:
power = line.split(":")[1]
#获取当前时间
currenttime = self.getCurrentTime()
#将获取到的数据存到数组中
self.alldata.append((currenttime, power))
#多次测试过程控制
def run(self):
#设置手机进入非充电状态
os.popen("adb shell dumpsys battery set status 1")
while self.counter >0:
self.testprocess()
self.counter = self.counter - 1
#每5秒钟采集一次数据
time.sleep(5)
#获取当前的时间戳
def getCurrentTime(self):
currentTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
return currentTime
#数据的存储
def SaveDataToCSV(self):
csvfile = file('meminfo.csv', 'wb')
writer = csv.writer(csvfile)
writer.writerows(self.alldata)
csvfile.close()
if __name__ == "__main__":
controller = Controller(5)
controller.run()
controller.SaveDataToCSV()

拓展:

  1. 功耗测试中的测试子项:
    1、手机安装目标APK前后待机功耗无明显差异
    2、常见使用场景中能够正常进入待机,待机电流在正常范围内
    3、长时间连续使用应用无异常耗电现象

  2. 功耗测试方法:
    方法一:软件
    1、采用市场上提供的第三方工具,如金山电池管家之类的。
    2、就是自写工具进行,这里一般会使用3种方法:
    1)基于android提供的PowerManager.WakeLock来进行
    2)比较复杂一点,功耗的计算=CPU消耗+Wake lock消耗+数据传输消耗+GPS消耗+Wi-Fi连接消耗
    3)通过 adb shell dumpsys battery来获取
    3、battery-historian(google开源工具)
    方法二:硬件
    一般使用万用表或者功耗仪安捷伦进行测试,使用功耗仪测试的时候,需要制作假电池来进行的,有些不能拔插电池的手机还需要焊接才能进行功耗测试

5 GPU(FPS)

shell:adb shell dumpsys gfxinfo com.xxxxx.xxxx

待完善-------------------------

拓展:

  1. 概念:
    过度绘制: 界面显示的activity套接了多层而导致
    帧率:屏幕滑动帧速率
    帧方差: 屏幕滑动平滑度
    **FPS:**Frames Per Second 每秒显示的帧数 根据人眼的生理结构,帧率高于24时就被认为是连贯的。对于游戏画面30fps是最低能接受的,60fps逼真感,如果帧率高于屏幕刷新频率就是浪费。要达到30fps,每帧所占用的时间要小于33毫秒

  2. GPU测试中的测试子项:
    1、界面过度绘制
    2、屏幕滑动帧速率
    3、屏幕滑动平滑度

  3. 过度绘制测试:(人工进行测试)
    打开开发者选项中的显示GPU过度绘制(Debug GPU overdraw)
    验收的标准:
    1、不允许出现黑色像素
    2、不允许存在4x过度绘制
    3、不允许存在面积超过屏幕1/4区域的3x过度绘制(淡红色区域)

  4. 屏幕滑动帧速率测试:
    方法一:
    1.手机端打开开发者选项中的启用跟踪后勾选Graphics和View
    2.启动SDK工具Systrace,勾选被测应用,点击Systrace,在弹出的对话框中设置持续抓取时间,在trace taps下面勾选gfx及view选项
    3.手工滑动界面可以通过节拍来进行滑动或者扫动,帧率数据会保存到默认路径下,默认名称为trace.html
    4.将trace.html文件拷贝到linux系统下通过命令进行转换,生成trace.csv文件
    grep 'postFramebuffer' trace.html | sed -e 's/.]\W//g' -e 's/:.*$//g' -e 's/.//g' > trace.csv
    5.用excel打开文件计算得到帧率
    方法二:
    硬件的方法,打开高速相机,开启摄像模式,录制手工滑动或者扫动被测应用的视频,再通过人工或者程序数帧的方法对结果进行计算得到帧率

  5. 屏幕滑动平滑度的测试:
    方法如同帧率测试,唯一的差异就是最后的结果计算公式的差异

  6. 捕获app帧率(android流畅度FPS测试):
    1、打开手机开发者选项,勾选GPU显示配置文件(系统会记录保留每个界面最后128帧图像绘制的相关时间信息)
    2、adb shell dumpsys gfxinfo com.xxx.xxx > zinfo.txt
    3、结果数据分析
    Profile data in ms部分:
    Draw: 创建显示列表的时间(DisplayList),所有View对象OnDraw方法占用的时间
    Process: Android 2D渲染引擎执行显示列表所花的时间,View越多时间越长
    Execute:将一帧图像交给合成器(compsitor)的时间,较小

  7. 其他工具:
    GameBench 测试android app的FPS工具
    Gfxinfo 查看app绘制性能工具

Android专项测试监控资源的更多相关文章

  1. 推荐支付宝 Android 专项测试工具SoloPi

    推荐支付宝 Android 专项测试工具SoloPi 1 介绍 SoloPi是一个无线化.非侵入式的Android自动化工具,公测版拥有录制回放.性能测试.一机多控三项主要功能,能为测试开发人员节省宝 ...

  2. 9.2专项测试-Android性能测试黑盒分析-1

    1. 专项测试 业务测试:面向新需求 回归测试:面向已交付需求 专项测试:面向非功能需求的各类质量唯独特征 表现 用户维度 技术维度 崩溃 crash,弱网 检测崩溃1.某个页面,因为研发处理不合适, ...

  3. 移动App专项测试

    移动App测试实战—专项测试 转自:http://www.51testing.com/html/58/n-3713758.html 我们在进行了手工的功能测试之后,也开发了一些自动化测试用例,并且做了 ...

  4. app专项测试

    本节为大家讲述app的专项测试——客户端性能测试.这个我也做了蛮久的了.在这里修改了一下本篇随笔. 首先我们了解一下什么是客户端的性能测试.性能测试相比大家都已经耳熟能详了,这个app的客户端性能测试 ...

  5. Android测试(一):在Android中测试App

    原文:https://developer.android.com/training/testing/index.html 测试你的App是开发过程中的重要组成部分.通过对应用程序持续的运行测试,你可以 ...

  6. 移动App测试实战—专项测试

       我们在进行了手工的功能测试之后,也开发了一些自动化测试用例,并且做了性能测试之后,测试工作看似比较完整了.但是当我们的App在大量的用户那里被安装和使用的时候,还是会有很多我们之前没有预料的问题 ...

  7. 移动性能测试 | 持续集成中的 Android 稳定性测试

    前言 谈到Android稳定测试,大多数会联想到使用monkey工具来做测试.google官方提供了monkey工具,可以很快速点击被应用,之前我有一篇帖子提到了monkey工具的使用,详见: htt ...

  8. 专项测试-App性能分析

    专项测试 app性能 Activity是Android组件中最基本也是最为常见用的四大组件(Activity,Service服务,Content Provider内容提供者,BroadcastRece ...

  9. Android开源测试框架学习

    近期因工作需要,分析了一些Android的测试框架,在这也分享下整理完的资料. Android测试大致分三大块: 代码层测试 用户操作模拟,功能测试 安装部署及稳定性测试 代码层测试 对于一般java ...

随机推荐

  1. Java Script入门

    学习来源:https://www.runoob.com/js/js-tutorial.html JavaScript 教程 JavaScript 是 Web 的编程语言. 所有现代的 HTML 页面都 ...

  2. java面试01-网络知识

    1.网络七层协议 第一层:物理层 机械.电子.定时接口通信信道上的原始比特流传输 第二层:数据链路层 物理寻址,同时将原始比特流转变为逻辑传输线路 第三层:网络层 控制子网的运行‘如逻辑编址.分组传输 ...

  3. LCA统计

    读入挂 inline void read(int &v) { v = ; ; ; ') { if (c == '-') { p = -; } c = getchar(); } ') { v = ...

  4. Python核心技术与实战——十七|Python并发编程之Futures

    不论是哪一种语言,并发编程都是一项非常重要的技巧.比如我们上一章用的爬虫,就被广泛用在工业的各个领域.我们每天在各个网站.App上获取的新闻信息,很大一部分都是通过并发编程版本的爬虫获得的. 正确并合 ...

  5. source insight支持查看makefile、kconfig以及.s代码方法

    在用sourceinsight查看linux内核源码的时候,大家会发现不能查看源码中的makefile和kconfig代码,即不能搜索到makefile和kconfig文件.这是因为source in ...

  6. Lengauer-Tarjan算法的相关证明

    Lengauer-Tarjan算法的相关证明 0. 约定 为简单起见,下文中的路径均指简单路径(事实上非简单路径不会对结论造成影响). \(V\)代表图的点集,\(E\)代表图的边集,\(T\)代表图 ...

  7. 阅读之spring框架

    资源表示:Resource Spring框架内部使用org.springframework.core.io.Resouce接口作为所有资源的抽象和访问接口. 它继承了 org.springframew ...

  8. HDU-2732-leapin'Lizards(最大流, 拆点)

    链接: https://vjudge.net/problem/HDU-2732 题意: Your platoon of wandering lizards has entered a strange ...

  9. 【NOIP2016提高A组模拟8.17】(雅礼联考day1)Matrix

    题目 分析 假设,我们从\(F_{i,2}\)出发,那么对\(F_{n,n}\)的贡献就是\(某个系数乘以a^{n-i}b^{n-1}r_i\): 同理,如果从\(F_{2,i}\)出发,那么对\(F ...

  10. JVM基础——面试、笔试

    1.java内存与内存溢出 1.1 JVM分为哪些区,每一个区干嘛的?(见java虚拟机38页) (1)程序计数器(线程私有) 当前线程执行字节码的信号指示器.(每个线程都会在程序计数器中存储其指令, ...