版本號 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繪制性能工具