Android 效能測試 - CPU
1、前言
很多時候在使用APP的時候,手機可能會發熱發燙。這是因為CPU使用率過高,CPU過於繁忙,會使整個手機無法響應使用者,整體效能降低,使用者體驗就會很差,也容易引起ANR等等一系列問題。以下會根據實際app效能測試案例,展開進行app效能評測之CPU使用率的分析和總結。
CPU使用率原理理解
在Linux系統下,CPU利用率分為使用者態、系統態、空閒態,分別表示CPU處於使用者態執行的時間,系統核心執行的時間,和空閒系統程序執行的時間。
平時所說的CPU利用率是指:CPU執行非系統空閒程序的時間 / CPU總的執行時間。
那麼我們來看看這個時間究竟是什麼?
先介紹幾個和Linux時間有關的名詞:HZ、tick與jiffies。
HZ :Linux 核心每隔固定週期會發出timer interrupt (IRQ 0),HZ是用來定義每一秒有幾次timer interrupts。例如HZ為1000,就代表每秒有1000次timer interrupts。
Tick :Tick是HZ的倒數,Tick = 1/HZ 。即timer interrupt每發生一次中斷的時間。如HZ為250時,tick為4毫秒(millisecond)。
Jiffies :在Linux的核心中,有一個全域性變數:Jiffies。 Jiffies代表時間。它的單位隨硬體平臺的不同而不同。jiffies的單位就是 1/HZ。Intel平臺jiffies的單位是1/100秒,這就是系統所能分辨的最小時間間隔了。每個CPU時間片,Jiffies都要加1。 CPU的利用率就是用執行使用者態+系統態的Jiffies除以總的Jifffies來表示。
CPU利用率計算公式也就是:
CPU使用率=(使用者態Jiffies+系統態Jiffies)/總Jiffies
2、CPU測試方法
2.1 CPU佔用率資料獲取方法--adb命令
CPU是系統非常重要的資源,在Android中/proc/stat, 包含了所有CPU的相關詳情資訊,檢視CPU使用情況,CPU不是一個瞬時態,而是一個過程態的體現,一般可以使用top命令和dump cpuinfo命令進行CPU佔用率獲取。
一般獲取Android CPU資料的有兩個命令:top和dump cpuinfo
(1)top命令方式獲取原理了解:
top是比較經典的CPU計算方法,top的程式碼在androidm/system/core/toolbox/top.c下面,輸出process的cpu使用率在print_procs裡面,CPU的計算是proc->delta_time * 100 / total_delta_time
先看total_delta_time由:
total_delta_time = (new_cpu.utime + new_cpu.ntime + new_cpu.stime + new_cpu.itime + new_cpu.iowtime + new_cpu.irqtime + new_cpu.sirqtime) - (old_cpu.utime + old_cpu.ntime + old_cpu.stime + old_cpu.itime + old_cpu.iowtime + old_cpu.irqtime + old_cpu.sirqtime);
而這些變數的值,是在read_procs通過讀取/proc/stat的jiffies得到:
所以總的cpu時間 = user + nice + system + idle + iowait + irq + softirq ,例如:User 147 + Nice 11 + Sys 79 + Idle 408 + IOW 1 + IRQ 0 + SIRQ 6 = 652
而proc->delta_time是兩次讀取/proc/pid/stat相減得到,可見,top是一段時間內,計算process的cpu jiffies與總的cpu jiffies差值得到。
註釋:
/proc/stat檔案:
該檔案包含了所有CPU活動的資訊,該檔案中的所有值都是從系統啟動開始累計到當前時刻。不同核心版本中該檔案的格式可能不大一致。
- user (147):
從系統啟動開始累計到當前時刻,處於使用者態的執行時間,不包含 nice值為負程序。 - nice (11):
從系統啟動開始累計到當前時刻,nice值為負的程序所佔用的CPU時間 - system (79):
從系統啟動開始累計到當前時刻,處於核心態的執行時間 - idle (408):
從系統啟動開始累計到當前時刻,除IO等待時間以外的其它等待時間 - iowait (1):
從系統啟動開始累計到當前時刻,IO等待時間(since 2.5.41) - irq (0)
從系統啟動開始累計到當前時刻,硬中斷時間(since 2.6.0-test4) - softirq (6):
從系統啟動開始累計到當前時刻,軟中斷時間(since 2.6.0-test4)
(2)top命令獲取CPU佔用率例項:
adb shell top -m 100 -n 1 -s cpu | grep 包名
adb shell top -m 100 -n 1 -s cpu | grep com.pafinancialtech.fuzhoubank auto:auto$ adb shell top -m 100 -n 1 -s cpu | grep com.pafinancialtech.fuzhoubank 18540042% S108 2102520K 317264Kfg u0_a858com.pafinancialtech.fuzhoubank

CPU佔用率_實時列印

CPU佔用率_5s間隔
2.2.2 dump cpuinfo命令獲取方法
(1)dump命令方式獲取原理了解:
dump cpuinfo是Android特有的命令,dump cpuinfo命令的實現在 androidm/frameworks/base/core/java/com/android/internal/os/ProcessCpuTracker.java 類裡面,方法是printCurrentState:
而printProcessCPU輸出process CPU的使用情況:
private void printProcessCPU(PrintWriter pw, String prefix, int pid, String label, int totalTime, int user, int system, int iowait, int irq, int softIrq, int minFaults, int majFaults) { pw.print(prefix); if (totalTime == 0) totalTime = 1; printRatio(pw, user+system+iowait+irq+softIrq, totalTime); ... }
user+system+iowait+irq+softIrq就是totalTime。 st變數的賦值,在collectStats裡面,st.rel_utime 和 st.rel_stime還是通過讀/proc/pid/stat相減得到,而st.rel_uptime卻是通過 SystemClock.uptimeMillis()差值,並不是跟top一樣,通過proc/stat得到總CPU jiffies,
所以,程序的總Cpu時間processCpuTime = utime + stime + cutime + cstime,該值包括其所有執行緒的cpu時間。(例外,一般cpu按100%計算,如果是多核情況下還需乘以cpu的個數)
附註釋:
/proc/pid/stat檔案:
該檔案包含了某一程序所有的活動的資訊,該檔案中的所有值都是從系統啟動開始累計 到當前時刻。
Utime(39) 該任務在使用者態執行的時間,單位為jiffies
Stime(25) 該任務在核心態執行的時間,單位為jiffies
Cutime(0) 所有已死執行緒在使用者態執行的時間,單位為jiffies
Cstime(0) 所有已死在核心態執行的時間,單位為jiffies
(2)dump命令獲取CPU佔用率例項
adb shell dumpsys cpuinfo |grep 包名
auto:auto$ adb shell dumpsys cpuinfo |grep com.pafinancialtech.fuzhoubank 117% 16322/com.pafinancialtech.fuzhoubank: 106% user + 11% kernel / faults: 45403 minor 99 major 0.5% 14032/com.pafinancialtech.fuzhoubank:pushservice: 0.5% user + 0% kernel / faults: 1610 minor +0% 16547/com.pafinancialtech.fuzhoubank:remote: 0% user + 0% kernel

CPU_dump方式獲取的佔用率
2.3 CPU問題分析思路及工具
如果APP某場景進行操作時出現發燙、卡頓、ANR現象時,可以懷疑出現CPU問題,一般解決思路如下:
a. 如果已經導致ANR, 則去log裡面搜尋"ANR in"
b. 沒有導致ANR則基於以上方法獲取到的CPU佔用率,如果某場景的CPU佔用率走勢異常、峰值存在異常、均值大於基線,則可以利用DDMS檢視分析Trace檔案,或者使用Android studio裡面的Android Monitor根據Monitor中的CPU可以看出目前CPU明細使用。
c.查詢程式中有沒有特殊佈局或者特殊操作(GPS定位,一直重新整理類的服務等),特殊載入(Gif圖片載入,視訊,音訊載入等)
2.3.1 Android Monitor監控分析
拿到APP原始碼,在Android studio中構建測試DEBUG包進行除錯如下截圖:

cpu_monitor

cpu_monitor
雙擊我綠色框標記的這個按鈕,就會生成這麼一個檔案,如圖:

cpu_monitor
上圖就一目瞭然的看到了耗費CPU 都有哪些方法。此時點選黑色的文字,幾秒鐘後studio會生成.trace檔案,我們就可以分析各方法使用cpu的情況了。
2.3.2 分析TraceView檔案查詢CPU問題
TraceView 是 Android SDK 中內建的1個工具,它可以載入 trace 檔案,用圖形的情勢展現程式碼的履行時間、次數及呼叫棧,便於我們分析。
(1)使用Android Studio工具DDMS
生成Traceview 進行分析檢視具體Trace期間各方法呼叫關係,呼叫次數以及耗時比例

DDMS_檢視各方法呼叫及CPU資訊
附註釋:
Traceview 面板分上下兩部分
上面是時間軸面板 (Timeline Panel)
左側顯示的是執行緒資訊
右側黑色部分是顯示執行時間段、白色是執行緒暫停時間段,
右側滑鼠放在上面會出現時間線縱軸,在頂部會顯示當前時間線所執行的具體函式資訊
下面是分析面板(Profile Panel) - 每一列內容
Inclusive time - 函式本身執行花費時間 + 函式呼叫其他函式時間
Exclusive time - 函式本身執行花費時間。
Calls + RecurCall/Total 呼叫 + 重複呼叫次數 / 函式總呼叫次數
Cpu Time/Call 總的Cpu時間與總的呼叫次數之比
附: Profile Panel各列作用說明
- Name
該執行緒執行過程中所呼叫的函式名 - Incl Cpu Time
某函式佔用的CPU時間,包含內部呼叫其它函式的CPU時間 - Excl Cpu Time
某函式佔用的CPU時間,但不含內部呼叫其它函式所佔用的CPU時間 - Incl Real Time
某函式執行的真實時間(以毫秒為單位),內含呼叫其它函式所佔用的真實時間 - Excl Real Time
某函式執行的真實時間(以毫秒為單位),不含呼叫其它函式所佔用的真實時間 - Call+Recur Calls/Total
某函式被呼叫次數以及遞迴呼叫佔總呼叫次數的百分比 - Cpu Time/Call
某函式呼叫CPU時間與呼叫次數的比。相當於該函式平均執行時間 - Real Time/Call
同CPU Time/Call類似,只不過統計單位換成了真實時間
(2)使用程式碼生成 trace 檔案
Debug.startMethodTracing("shixintrace"); //開始 trace,儲存檔案到 "/sdcard/shixintrace.trace" // ... Debug.stopMethodTracing();//結束
程式碼很簡單,當你呼叫開始程式碼的時候,系統會生產 trace 檔案,並且產生追蹤資料,當你呼叫結束程式碼時,會將追蹤資料寫入到 trace 檔案中。
下1步使用 adb 命令將 trace 檔案匯出到電腦:
adb pull /sdcard/shixintrace.trace /tmp
使用程式碼生成 trace 方式的好處是容易控制追蹤的開始和結束,缺點就是步驟略微多了一點。
2.3 CPU測試場景
一般cpu檢測我們要分4種情況:
1.在空閒時間的消耗,基本沒大應用使用cpu
如果APP在退出介面後還有程序長期執行,那需要關注下待機場景的CPU。待機場景下CPU的消耗一般不會很大,例如銀行APP在後臺執行時,可能消耗經常是0%,長時間平均下,可能只有0.1%、0.2%,看看競品,也是差不多,好像沒有太大區別。那麼CPU消耗這麼少是不是就不用管CPU了呢,然而即使是平均值很小,但是長時間待機,例如安全類工具,CPU的消耗還是不容忽視。
這種場景下我們測試時常用的單位有:消耗XX jiffies/分鐘;半/1小時共增加XX jiffies。
2.在執行一些應用的情況下,cpu已佔50%的情況下,觀察應用程式佔用cpu的情況
簡單說這種情況就是後臺已經有幾個應用在執行已經並且消耗了系統的一些資源的情況下進行測試。
3.在高負荷的情況下看CPU的表現,我定義這個高負荷,cpu佔用應是在80%以上
滿規格狀態下的應用CPU消耗情況
4.觀察App 相同/不同場景下CPU走勢、峰值情況
對比不同場景頁面CPU佔用大小
對比不同時間段同一場景頁面CPU佔用走勢情況
3、XX銀行效能評測-CPU測試結果分析
3.1 總覽
效能測試的採集的CPU佔用資料主要是針對場景頁面的CPU佔用測試,CPU佔用資料獲取原理是CPU執行非系統空閒程序的時間 / CPU總的執行時間。
從CPU消耗對比來看,行業競品均值為8.4%,90分位約4.9%,75分位約7.8%,中位數約9.3%,25分位約16.2%。

CPU佔用對比
CPU佔用對比.png
【榕商Bank】和10家競品分析對比,CPU佔用12.0%,表現較差,不及行業平均水準。但是從APP本品各場景CPU佔用率來看,佔用率最大的為理財產品詳情頁22.7%,主要原因是該頁面存在6個不同時段近七日和萬份收益率曲線走勢圖繪製,但是仍然未超過CPU佔用率基線30%,且目前大部分手機是四核、八核系統,所以目前測試資料表明整體表現良好不存在瓶頸,但是從行業標準來看,理財產品詳情頁仍然有優化空間,建議優化。

理財產品詳情頁效能曲線
4、App端CPU問題排查思路:
(1)是否有非常多的網路請求
(2)是否開了很多程序OR 應用,嘗試關閉其他應用再檢視CPU是否降下來
(3)是否有大量大圖片、視訊處理跟載入或佈局
(4)查詢程式中有沒有特殊佈局或者特殊操作(GPS定位,一直重新整理類的服務等),特殊載入(Gif圖片載入,視訊,音訊載入等)
(5)當前頁面是否有過多的圖表、曲線圖等繪製操作
(6)通過Android Studio 自帶的monitor查詢是哪個Activity或者哪個方法有一直不停止的運算消耗CPU(比如:不停止的while 或者for 迴圈)