Android性能測試:(內存、cpu、fps、流量、GPU、電量)|adb篇

Android性能測試:(內存、cpu、fps、流量、GPU、電量)|adb篇

adb 常用命令

  1. 獲取連接設備號:adb devices

  2. 列出設備所有已安裝的包名 (不需root權限)

    adb shell “pm list packages”,可以加上grep 進行篩選(windows系統使用findstr /i "xxxx" 或者 find)

Android性能測試:(內存、cpu、fps、流量、GPU、電量)|adb篇

3.查看進程列表:adb shell "ps",同時也能獲取到應用的UID,方式如下(不需root權限):

Android性能測試:(內存、cpu、fps、流量、GPU、電量)|adb篇

u0_a開頭的都是Android的應用進程,Android的應用的UID是從10000開始,到19999結束,可以在Process.java中查看到(FIRST_APPLICATION_UID和LAST_APPLICATION_UID),u0_a後面的數字就是該應用的UID值減去FIRST_APPLICATION_UID所得的值,所以,對於截圖這個應用進程,它是u0_a155,按前面的規制,它的UID就是155 + FIRST_APPLICATION_UID = 10155。

內存說明

VSS - Virtual Set Size 虛擬耗用內存(包含共享庫佔用的內存)

RSS - Resident Set Size 實際使用物理內存(包含共享庫佔用的內存)

PSS - Proportional Set Size 實際使用的物理內存(比例分配共享庫佔用的內存)

USS - Unique Set Size 進程獨自佔用的物理內存(不包含共享庫佔用的內存)

一般來說內存佔用大小有如下規律:VSS >= RSS >= PSS >= USS

adb 查看單個內存佔用量 (均不需要root權限)

  1. 單個應用的最大內存限制

    adb shell "getprop | grep heapgrowthlimit"

  2. 應用啟動後分配的初始內存

    adb shell "getprop|grep dalvik.vm.heapstartsize"

  3. 單個java虛擬機的最大內存限制

    adb shell "getprop|grep dalvik.vm.heapsize"

Android性能測試:(內存、cpu、fps、流量、GPU、電量)|adb篇

Android性能測試:(內存、cpu、fps、流量、GPU、電量)|adb篇

Android性能測試:(內存、cpu、fps、流量、GPU、電量)|adb篇

adb內存數據採集

使用 adb shell "dumpsys meminfo -s "命令,輸出結果分以下4部分:

  1. process 以進程的PSS從大到小依次排序顯示,每行顯示一個進程;

  2. OOM adjustment 分別顯示每類的進程情況

  3. category 以Dalvik/Native/.art mmap/.dex map等劃分的各類進程的總PSS情況

  4. total 總內存、剩餘內存、可用內存、其他內存

執行結果如下圖,重點取該應用的TOTAL 對應的內存佔用大小(KB)

Android性能測試:(內存、cpu、fps、流量、GPU、電量)|adb篇

PS:在apk內調用運行獲取其他app的內存數據則需要root權限

adb fps(每秒幀數,計算流暢度)數據採集

adb命令:adb shell dumpsys gfxinfo

前提:開發者選項=>GPU呈現模式分析確保打開=>在adb shell dumpsys gfxinfo中or 在屏幕上顯示為線型圖

方法僅適用於Android原生應用,不適用於遊戲

正常情況下幀率應該在16.67ms左右,1秒60幀,執行結果如下:

Android性能測試:(內存、cpu、fps、流量、GPU、電量)|adb篇

詳細計算方法如下:

  1. 首先獲取執行一次命令打印出來的結果,重點關注Draw Prepare Process Execute 行下面的數據

    Draw:是消耗在構建java顯示列表DisplayList的時間。說白了就是執行每一個View的onDraw方法,創建或者更新每一個View的DisplayList對象的時間。

    Process:表示是消耗在Android的2D渲染器執行顯示列表的時間,view越多,要執行的繪圖命令就越多,時間就越長

    Execute:消耗在排列每個發送過來的幀的順序的時間.或者說是CPU告訴GPU渲染一幀的時間,這是一個阻塞調用,因為CPU會一直等待GPU發出接到命令的回覆。所以這個時間,一般都很短。

    Draw + Prepare+Process + Execute = 完整顯示一幀 ,這個時間要小於16ms才能保存每秒60幀。

  2. 計算總數據的行數 frame_count = row_num, 計算每行渲染時間render_time = Draw + Prepare+Process + Execute, 當渲染時間>16.67ms(1000/60),按照垂直同步機制,該幀已經渲染超時

  3. 一旦render_time>16.67 算一次jank(丟幀),一旦jank,需要用掉額外的vsync

    vsync_overtime = 向上取整(render_time/16.67) - 1

    比如:render_time = 66.68 vsync_overtime = 3

    render_time = 67 vsync_overtime = 4

    一次命令執行獲得的fps = int( frame_count * 60 / (frame_count + vsync_overtime_sum))

還有一個命令是: adb shell dumpsys SurfaceFlinger --latency LayerName

這個命令能獲取遊戲/視頻應用的fps數據

其中LayerName在各個不同系統中獲取的命令是不一樣的

在Android 6系統直接就是SurfaceView

在Android 7系統中可以通過 dumpsys window windows | grep mSurface | grep SurfaceView 然後通過數據截取到

在Android 8系統中可以通過 dumpsys SurfaceFlinger | grep android包名獲取到

執行命令結果如下:

Android性能測試:(內存、cpu、fps、流量、GPU、電量)|adb篇

計算方法比較簡單,一般打印出來的數據是129行(部分機型打印兩次257行,但是第一部分是無效數據,取後半部分),取len-2的第一列數據為end_time,取len-128的第一列數據為start_time

fps = 127/((end_time - start_time) / 1000000.0)

至於為啥要取第一列數據,這裡不做過多介紹

Android性能測試之fps獲取

至於為啥要處於1000000,因為命令打印出來的是納秒單位,要轉為毫秒進行計算,127就是因為命令一次打印出來127幀的數據而已

adb CPU佔用率數據採集

有兩種方法可以獲取

1) adb shell "top -n 5 | grep " ,第三列就是實時監控的CPU佔用率(-n 指定執行次數,不需root權限),這邊top命令執行需要2到3s左右,一般可以採用busybox 的top命令執行,效率會快很多

Android性能測試:(內存、cpu、fps、流量、GPU、電量)|adb篇

2) adb shell "dumpsys cpuinfo | grep "

兩種方法直接區別在於,top是持續監控狀態,而dumpsys cpuinfo獲取的實時CPU佔用率數據

adb 耗電量數據採集

adb命令:adb shell "dumpsys batterystats < package | pid>" (Android 5.0後引入)

獲取單個應用的耗電量信息,具體返回結果待研究

adb命令:adb shell "dumpsys battery"

出現信息解讀:

AC powered:false 是否連接AC(電源)充電線

USB powered:true 是否連接USB(PC或筆記本USB插口)充電

Wireless powered:false 是否使用了無線電源

status: 1 電池狀態,2為充電狀態,其他為非充電狀態

level:58 電量(%)

scale: 100. 電量最大數值

voltage: 3977 當前電壓(mV)

current now: -335232. 當前電流(mA)

temperature:355 電池溫度,單位為0.1攝氏度

technology:Li-poly. 電池種類

Android性能測試:(內存、cpu、fps、流量、GPU、電量)|adb篇

adb 採集流量數據

adb 命令:adb shell "dumpsys< package | pid> | grep UID" [通過ps命令,獲取app的UID(安裝後唯一且固定)]

adb shell cat /proc/uid_stat/UID/tcp_rcv [cat為查看命令,讀取tcp_rcv獲取應用接收流量信息(設備重啟後清零)]

adb shell cat /proc/uid_stat/UID/tcp_snd [cat為查看命令,讀取tcp_snd獲取應用發送流量信息(設備重啟後清零)]

計算流量消耗步驟:

  1. 執行一次這兩條命令,獲取到應用的開始接收及發送的流量

  2. 然後我們再操作應用,執行一段時間測試

  3. 再次執行上述 2 條命令可以獲取到應用結束時候的接收及發送的流量,通過相減及得到應用的整體流量消耗

或者還有一種方式獲取應用流量消耗:

  1. 首先獲取應用固定uid

    dumsys package android包名 | grep userId

  2. 執行cat /proc/net/xt_qtaguid/stats | grep uid

Android性能測試:(內存、cpu、fps、流量、GPU、電量)|adb篇

其中第6列代表rx_bytes接收的字節數,第8列為tx_bytes發送的字節數
  1. 一個uid可能對應多個進程,把數據累加就行

    兩個時間片中間應用流量的消耗,就計算接收字節數的差值就行

adb採集CPU溫度

首先判斷類型:

cat /sys/class/thermal/thermal_zone*/type

Android性能測試:(內存、cpu、fps、流量、GPU、電量)|adb篇

只有紅框框出來的是有效的

cat /sys/class/thermal/thermal_zone*/temp

獲取CPU溫度

Android性能測試:(內存、cpu、fps、流量、GPU、電量)|adb篇

adb採集電池溫度

dumpsys battery | grep temperature 單位0.1攝氏度

Android性能測試:(內存、cpu、fps、流量、GPU、電量)|adb篇

adb 採集GPU佔用率

注意事項

  1. 所有dumpsys命令獲取性能數據,如果adb shell進入終端執行,均要求執行有root權限,如果PC端進入終端執行,則無此要求


程序爬蟲抓取有用資源共享給大家

關注後,私信回覆【資料包】獲取如下內容,


分享到:


相關文章: