版本号 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)空闲状态下的应用内存消耗情况
2)中等规格状态下的应用内存消耗情况
3)满规格状态下的应用内存消耗情况
4)应用内存峰值情况
5)应用内存泄露情况
6)应用是否常驻内存
7)压力测试后的内存使用情况 -
内存问题现象:
1)内存抖动
2)大内存对象被分配
3)内存不断增长
4)频繁GC -
内存数据获取:
1、各种linux命令(top、free、meminfo…)
2、通过dumpsysadb 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()
拓展:
-
CPU测试中的测试子项:
1)空闲状态下的应用CPU消耗情况
2)中等规格状态下的应用CPU消耗情况
3)满规格状态下的应用CPU消耗情况
4)应用CPU峰值情况 -
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
-
概念:
中等负荷:应用正常操作
高负荷:应用极限操作 -
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、应用首次启动流量值
2、应用后台连续运行 2 小时的流量值
3、应用高负荷运行的流量峰值
4、应用中等负荷运行时的流量均值 -
获取流量数据:
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、手机安装目标APK前后待机功耗无明显差异
2、常见使用场景中能够正常进入待机,待机电流在正常范围内
3、长时间连续使用应用无异常耗电现象 -
功耗测试方法:
方法一:软件
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
待完善-------------------------
拓展:
-
概念:
过度绘制: 界面显示的activity套接了多层而导致
帧率:屏幕滑动帧速率
帧方差: 屏幕滑动平滑度
**FPS:**Frames Per Second 每秒显示的帧数 根据人眼的生理结构,帧率高于24时就被认为是连贯的。对于游戏画面30fps是最低能接受的,60fps逼真感,如果帧率高于屏幕刷新频率就是浪费。要达到30fps,每帧所占用的时间要小于33毫秒 -
GPU测试中的测试子项:
1、界面过度绘制
2、屏幕滑动帧速率
3、屏幕滑动平滑度 -
过度绘制测试:(人工进行测试)
打开开发者选项中的显示GPU过度绘制(Debug GPU overdraw)
验收的标准:
1、不允许出现黑色像素
2、不允许存在4x过度绘制
3、不允许存在面积超过屏幕1/4区域的3x过度绘制(淡红色区域) -
屏幕滑动帧速率测试:
方法一:
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打开文件计算得到帧率
方法二:
硬件的方法,打开高速相机,开启摄像模式,录制手工滑动或者扫动被测应用的视频,再通过人工或者程序数帧的方法对结果进行计算得到帧率 -
屏幕滑动平滑度的测试:
方法如同帧率测试,唯一的差异就是最后的结果计算公式的差异 -
捕获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)的时间,较小 -
其他工具:
GameBench 测试android app的FPS工具
Gfxinfo 查看app绘制性能工具