天天看點

Android性能測試(記憶體、cpu、fps、流量、GPU、電量)——adb篇

作者:Android不是安卓

adb 常用指令

  1. 擷取連接配接裝置号:adb devices
  2. 列出裝置所有已安裝的包名 (不需root權限)

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

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. 單個應用的最大記憶體限制
  2. adb shell "getprop | grep heapgrowthlimit"
  3. 應用啟動後配置設定的初始記憶體
  4. adb shell "getprop|grep dalvik.vm.heapstartsize"
  5. 單個java虛拟機的最大記憶體限制
  6. adb shell "getprop|grep dalvik.vm.heapsize"

adb記憶體資料采集

使用 adb shell "dumpsys meminfo -s <pakagename | pid>"指令,輸出結果分以下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 <package | pid>

前提:開發者選項=>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)

至于為啥要取第一列資料,這裡不做過多介紹,歡迎參看這兩篇文章

老羅的文章SurfaceView原理

Android性能測試之fps擷取

至于為啥要處于1000000,因為指令列印出來的是納秒機關,要轉為毫秒進行計算,127就是因為指令一次列印出來127幀的資料而已

adb CPU占用率資料采集

有兩種方法可以擷取

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

Android性能測試(記憶體、cpu、fps、流量、GPU、電量)——adb篇

2) adb shell "dumpsys cpuinfo | grep <package | pid>"

兩種方法直接差別在于,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
  3. 其中第6列代表rx_bytes接收的位元組數,第8列為tx_bytes發送的位元組數

    一個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采集整機CPU使用率和分核CPU使用率

擷取/proc/stat檔案内容(無權限限制)

Android性能測試(記憶體、cpu、fps、流量、GPU、電量)——adb篇
Android性能測試(記憶體、cpu、fps、流量、GPU、電量)——adb篇

總的cpu時間片是 total = user+nice+system+idle+iowait+irq+softirq

忙碌時間為 notidle = user+nice+system +iowait+irq+softirq

cpu使用率計算方法為,先取開始的total值和忙碌時間notidle,隔一段時間片,再取一次計算total2,notidle2, cpuuse = (notidle2 – notidle) * 100 / (total2 - total)%

PS:由于Android 8權限收緊,在Android 8系統手機内apk内讀取檔案内容為空,需要shell權限才可擷取檔案内容,下同

adb 采集各核cpu頻率

讀/sys/devices/system/cpu/cpuX/cpufreq/scaling_cur_freq檔案的值,X不定,看是幾核手機,scaling_cur_freq是否存在也不一定,需要判斷

至于為啥不取cpuinfo_cur_freq檔案的值,原因是android 6,7系統擷取的時候,這個檔案shell沒有讀取權限,需要root權限

Android性能測試(記憶體、cpu、fps、流量、GPU、電量)——adb篇

adb擷取目前運作于手機前端的應用的包名

Android 6,7系統可執行

dumpsys window windows | grep "mCurrentFocus"

執行結果一般為類似:

mCurrentFocus=Window{81caaa5 u0 com.tencent.mobileqq/com.tencent.mobileqq.activity.SplashActivity}

按照一定規則把com.tencent.mobileqq提取出來即可

adb 采集GPU占用率,目前支援高通GPU晶片(Qualcomm Adreno系列)

直接apk内讀取檔案即可,不需要shell權限(支援到Android8)

Gpu使用率擷取:會得到兩個值,(前一個/後一個)*100%=使用率

adb shell cat /sys/class/kgsl/kgsl-3d0/gpubusy

Gpu工作頻率:

adb shell cat /sys/class/kgsl/kgsl-3d0/gpuclk

adb shell cat /sys/class/kgsl/kgsl-3d0/devfreq/cur_freq

Gpu最大、最小工作頻率:

adb shell cat /sys/class/kgsl/kgsl-3d0/devfreq/max_freq

adb shell cat /sys/class/kgsl/kgsl-3d0/devfreq/min_freq

Gpu可用頻率

adb shell cat /sys/class/kgsl/kgsl-3d0/gpu_available_frequencies

adb shell cat /sys/class/kgsl/kgsl-3d0/devfreq/available_frequencies

Gpu可用工作模式:

adb shell cat /sys/class/kgsl/kgsl-3d0/devfreq/available_governors

Gpu目前工作模式:

adb shell cat /sys/class/kgsl/kgsl-3d0/devfreq/governor

注意事項

  1. 所有dumpsys指令擷取性能資料,如果adb shell進入終端執行,均要求執行有shell權限,如果PC端進入終端執行,則無此要求