<轉>Android App性能評測分析-cpu佔用篇

一、前言

不少時候在使用APP的時候,手機可能會發熱發燙。這是由於CPU使用率太高,CPU過於繁忙,會使整個手機沒法響應用戶,總體性能下降,用戶體驗就會不好,也容易引發ANR等等一系列問題。如下會根據實際app性能測試案例,展開進行app性能評測之CPU使用率的分析和總結。html

CPU使用率原理理解

在Linux系統下,CPU利用率分爲用戶態、系統態、空閒態,分別表示CPU處於用戶態執行的時間,系統內核執行的時間,和空閒系統進程執行的時間。java

平時所說的CPU利用率是指:CPU執行非系統空閒進程的時間 / CPU總的執行時間。android

那麼咱們來看看這個時間到底是什麼?shell

先介紹幾個和Linux時間有關的名詞:HZ、tick與jiffies。api

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)/總Jiffiesruby

二、CPU測試方法

2.1 CPU佔用率數據獲取--第三方測試工具

騰訊GT
平安雲測試助手+評測中心(http://fit-stg1.jryzt.com/Hyperion-server/html/index.html) ---極力推薦
安測試
騰訊APT
網易Emageebash

CPU測試你們通常都使用外部提供的第三方工具來輔助測試,相似上方列舉的這些、這些工具的原理都是基於調用 android 底層的一些 api 來獲取到測試所用到的值,固然咱們也能夠採用其餘方法,如使用 android 自己提供的一套 adb 便可完成上述測試。網絡

2.2 CPU佔用率數據獲取方法--adb命令

CPU是系統很是重要的資源,在Android中/proc/stat, 包含了全部CPU的相關詳情信息,查看CPU使用狀況,CPU不是一個瞬時態,而是一個過程態的體現,通常可使用top命令和dump cpuinfo命令進行CPU佔用率獲取。app

通常獲取Android CPU數據的有兩個命令:top和dump cpuinfo

2.2.1 top命令獲取方法

(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

zhangmeiyuan-5:~ zhangmeiyuan$ adb shell top -m 100 -n 1 -s cpu | grep com.pafinancialtech.fuzhoubank
18540  0  42% S   108 2102520K 317264K  fg u0_a858  com.pafinancialtech.fuzhoubank
 
CPU佔用率_實時打印.png

 

 
CPU佔用率_每隔5s打印一次.png

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 包名

zhangmeiyuan-5:~ zhangmeiyuan$ 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方式獲取的佔用率.png

 

從上圖咱們能夠看出:80%是針對這個CPU的佔用率是80%,其中72%佔用率是用戶使用的,8.4%是內核的佔用率,這個數只是針對1核來講,如今手機都是多核的了,那這樣的值也不會太準確,若是是多核狀況下還需除以cpu的個數。

綜上:top跟dump cpuinfo的區別在於:top分母是總測CPU jiffies,而dump cpuinfo是是時間,而並不是jiffies,也能解釋爲何top出來的cpu,大部分時間會比dump cpuinfo小的緣由。

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.png

 

 
image.png

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

 

 
image.png

 

上圖就一目瞭然的看到了耗費CPU 都有哪些方法。此時點擊黑色的文本,幾秒鐘後studio會生成.trace文件,咱們就能夠分析各方法使用cpu的狀況了。

2.3.2 分析TraceView文件查找CPU問題

TraceView 是 Android SDK 中內置的1個工具,它能夠加載 trace 文件,用圖形的情勢展示代碼的履行時間、次數及調用棧,便於咱們分析。

(1)使用Android Studio工具DDMS

生成Traceview 進行分析查看具體Trace期間各方法調用關係,調用次數以及耗時比例

 

 
DDMS_查看各方法調用及CPU信息.png

附註釋:
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佔用走勢狀況

三、XX銀行性能評測-CPU測試結果分析

3.1 總覽

這次質量開放平臺-評測中心(http://fit-stg1.jryzt.com/Hyperion-server/html/index.html)的性能測試的採集的CPU佔用數據主要是針對場景頁面的CPU佔用測試,CPU佔用數據獲取原理是CPU執行非系統空閒進程的時間 / CPU總的執行時間。

從CPU消耗對比來看,行業競品均值爲8.4%,90分位約4.9%,75分位約7.8%,中位數約9.3%,25分位約16.2%。

 

 
CPU佔用對比.png

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

 

 
理財產品詳情頁性能曲線.png

四、App端CPU問題排查思路:

(1)是否有很是多的網絡請求
(2)是否開了不少進程OR 應用,嘗試關閉其餘應用再查看CPU是否降下來
(3)是否有大量大圖片、視頻處理跟加載或佈局
(4)查找程序中有沒有特殊佈局或者特殊操做(GPS定位,一直刷新類的服務等),特殊加載(Gif圖片加載,視頻,音頻加載等)
(5)當前頁面是否有過多的圖表、曲線圖等繪製操做
(6)經過Android Studio 自帶的monitor查找是哪一個Activity或者哪一個方法有一直不中止的運算消耗CPU(好比:不中止的while 或者for 循環)

 
 
 做者:蕭竹 出處:https://www.jianshu.com/u/88caeb7696f5  本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。
相關文章
相關標籤/搜索