APP性能(Monkey)【启动时间、CPU、流量、电量、内存、FPS、过度渲染】
APP性能测试—启动时间
冷启动—程序完全关闭时的启动
启动:adb shell am start -W -n package/activity
停止:adb shell am force-stop package
热启动—程序退到后台,并未完全杀死时的启动
启动:adb shell am start -W -n package/activity
停止:adb shell input keyevent 3 3表示点击手机上的back键
【启动时间】数据分析
1、取一个启动时间的平均值(如果运行10次,一般把第1次去掉。取后面9次的数据)
2、画一个曲线图
3、怎么确定我们的启动时间是否正常?可以和市场上的同类产品的平均值对比,也可以和 自己的APP历史版本对比
【启动时间】性能测试脚本
#coding:utf8 import os,time,csv #APP类 class App(object): def __init__(self): self.content="" self.startTime="0" #启动APP com.android.browser/.BrowserActivity def LaunchApp(self): cmd='adb shell am start -W -n package/activity' self.content=os.popen(cmd) #执行cmd,并将执行结果赋值给变量 content #测试冷启动和热启动APP的区别在于停止方法 #停止APP,用于冷启动的APP def StopApp(self): cmd='adb shell am force-stop package' os.popen(cmd) #执行cmd #停止APP,用于热启动的APP # def StopApp(self): # cmd='adb shell input keyevent 3'#触发手机上的back键,实现退出 # os.popen(cmd) #执行cmd #获取启动时间 def GetLaunchedTime(self): for line in self.content.readlines(): if "ThisTime" in line: self.startTime=line.split(":")[1] break return self.startTime #控制类 class Controller(object): def __init__(self,count): self.app=App() self.count=count self.alldata=[("timestamp","elapsedtime")] #单次测试过程 def testprocess(self): self.app.LaunchApp() time.sleep(5) elapsedtime=self.app.GetLaunchedTime() self.app.StopApp() time.sleep(3) currentTime=self.getCurrentTime() #将时间戳存到数组里 self.alldata.append((currentTime,elapsedtime)) #多次执行测试过程。用while循环,现在__init__里定义执行次数的参数,每执行一次,自减1 直到完成 def run(self): while self.count>0: self.testprocess() self.count-=1 #获取当前的时间戳 def getCurrentTime(self): currentTime=time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()) return currentTime #数据的存储 def SaveDataToCSV(self): csvfile=file('startTime.csv','wb') write=csv.write(csvfile) #将alldata的数据写入write write.writerows(self.alldata) csvfile.close() if __name__=='__main__': #实例化 controller=Controller(10) #调用run方法 controller.run() #调用SaveDataToCSV方法 controller.SaveDataToCSV()
APP性能测试—CPU
获取CPU数据:adb shell dumpsys cpuinfo | grep package
【CPU】数据分析
可以配合操作脚本加上监控命令去测试CPU,这样更接近实际使用情况.如果CPU使用率一直上升,没有下降.或者达到100%/80% 等等,就说明有问题了
【CPU】性能测试脚本
#coding:utf8 import csv,os,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 | grep package") 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(5) #获取当前的时间戳 def getCurrentTime(self): currentTime=time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()) return currentTime #数据的存储 def saveDataCSV(self): csvfile=file('cpustatus.csv','wb') writer=csv.writer(csvfile) writer.writerrows(self.alldata) csvfile.close() if __name__='__main__': controller=Controller(10) controller.run() controller.saveDataCSV()
APP性能测试—流量
获取进程ID:adb shell ps | grep(findstr) package
根据进程ID获取流量:adb shell cat/proc/pid/net/dev pid代表进程ID号,其余照抄
结果:
Receive APP接收的数据
Transmit APP发出的数据
这2个加上的总值就是这个APP使用的流量,eth0 和eth1代表2个网卡的流量数据
【流量】性能测试脚本
#coding:utf8 import time,os,csv,string #控制类 class Controller(object): def __init__(self,count): #定义测试的参数 self.counter=count #定义收集数据的数组 self.alldata=[('timestamp','traffic')] #单次测试过程 def testprocess(self): #执行获取进程ID的命令 result=os.popen('adb shell ps | grep packagename') #获取进程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] transmt=line.split('#')[9] elif "eth1" in line: #将所有空行换成# line='#'.join(line.split()) #按#号拆分,获取收到和发出的流量 receive2=line.split('#')[1] transmt2=line.split('#')[9] #计算所有流量之和 alltraffic=string.atoi(receive)+string.atoi(transmit)+string.atoi(receive2)+string.atoi(transmit2) #按KB计算流量值,因为获取到的值是bit单位,除以1024就换算成了KB为单位的流量值 alltraffic=alltraffic/1024 #获取当前时间 currenttime=self.getCurrentTime() #将获取到的数据存储到数组中 self.alldata.append((currenttime,alltraffic)) #多次测试过程 def run(self): while self.counter>0: self.testprocess() self.counter-=1 #每5秒钟采集1次数据 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.writerrows(self.alldata) csvfile.close() if __name__='__main__': controller=Controller(3) controller.run() controller.saveDataToCSV()
APP性能测试—电量
获取电量命令:adb shell dumpsys battery
返回值:level值表示电量
切换非充电状态 命令:adb shell dumpsys battery set status 1
Status 值为什么设置为1呢?其实只要非2就可以了,因为2是代表充电状态
【电量】性能测试脚本
#coding:utf8 import csv,os,time #控制类 class Controller(object): def __init__(self,count): 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-=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('power.csv','wb') writer=csv.writer(csvfile) writer.writerrows(self.alldata) csvfile.close() if __name__=='__main__': controller=Controller(3) controller.run() controller.saveDataToCSV()
APP性能测试—内存
获取内存命令:adb shell top
例:adb shell top -d 1 -d表示命令刷新的频率 1表示1秒种。上列命令表示1秒钟取一次内存的值
例:adb shell top -d 1 > meminfo 将结果输入到一个文件meminfo
Cat meminfo 查看数据文件meminfo 里面有刚才取到的所有内存数据
过滤meminfo里的数据,命令:Cat meminfo | grep package
内存的取值:
VSS Virtaul Set Size 虚拟耗用内存
RSS Resident Set Size 实际使用物理内存
取完值之后,做成曲线图 如果内存长期处于稳定状态,说明我们的APP没有内存泄露的情况
【内存】性能测试脚本
#coding:utf8 import csv,os,time #控制类 class Controller(object): def __init__: def __init__(self,count): #定义测试的参数 self.counter=count #定义收集数据的数组 self.alldata=[('timestamp','meminfo')] #分析数据 def analyzedata(self): content=self.readfile() i=0 for line in content: if "com.android.browser" in line: print line line="#".join(line.split()) vss=line.split("#")[5].strip("K") rss=line.split("#")[6].strip("K") #将获取到的数据存储到数组中 self.alldata.append((i,vss,rss)) i+=1 #数据的存储 def saveDataToCSV(self): csvfile=file('meminfo.csv','wb') writer=csv.writer(csvfile) writer.writerrows(self.alldata) csvfile.close() #读取数据文件 def readfile(self): mfile=file('meminfo','r') content=mfile.readlines() mfile.close() return content if __name__=="__main__": controller=Controller() controller.analyzedata() controller.saveDataToCSV()
APP性能测试—FPS
FPS:frames per second 每秒的帧数,每秒60帧认为是一个正常的帧数 如果大于60帧可以认为是一个卡帧的现象
FPS查看方式: 开发者选项 → GPU呈现模式分析
FPS查看结果:在屏幕上显示为条形图 手机下方会出现一个条形图。条形图的上方会有一根绿色的线,表示16毫秒 如果很多在绿线以上就代表FPS有问题,有卡帧的现象
APP性能测试—过度渲染
过度渲染:描述的时屏幕上的某个像素在同一帧的时间内被绘制了多次
过度渲染查看方式: 开发者选项 → GPU过度绘制
***END