Android移動客戶端性能測試淺談——電量

本文由做者張迎貞受權網易雲社區發佈。html


APP性能測試除了須要監控PCU、內存佔用、流量等,還須要獲取APP的電量數據,測試在可接受範圍內,避免APP出現過分消耗電量的現象。
手機有不少硬件模塊:CPU,藍牙,GPS,顯示屏,Wifi,射頻(Cellular Radio)等,在手機使用過程當中,這些硬件模塊可能處於不一樣的狀態,譬如WIFI打開或關閉,屏幕是亮仍是暗,CPU運行或休眠。 硬件模塊在不一樣的狀態下的耗電量是不一樣的。Android在進行電量統計時,並非採用直接記錄電流消耗量的方式,而是跟蹤硬件模塊在不一樣狀態下的使用時間,收集一些可用信息,用來近似的計算出電池消耗量。
從用戶使用層面來看,Android須要統計出應用程序的耗電量。應用程序的耗電量由不少部分組成,可能使用了GPS,藍牙等模塊,可能應用程序要求長時間亮屏(譬如遊戲、視頻類應用)。 一個應用程序的電量統計,能夠採用累計應用程序使用全部硬件模塊時間這種方式近似計算出來。
舉一個例子,假定某個APP使用了GPS,使用時間用 t 表示。GPS模塊單位時間的耗電量用 w 表示,那麼,這個APK使用GPS的耗電量就能夠按照以下方式計算:
耗電量 = 單位時間耗電量(w) × 使用時間(t)
python

測試方法多種多樣:android

一、CPU空閒時,停留在主界面不退出,打開網絡而後鎖屏,12小時後查看電量、流量變化
二、APP在操做運行時(此過程可藉助使用monkey進行壓力測試),1小時後查看電量、流量變化
三、第三方APP進行步驟一、2相同的場景測試
四、對比競品APP的耗電量。
指望結果:APP在靜止狀態時無沒有明顯的耗電狀況,在運行狀態時耗電量在可接受範圍內。
git

方法1——手機自帶

有的手機設置菜單裏面會有流量和電量統計類,只需在測試先後記錄下電量值,即可獲取消耗電量數值。github

 

方法2——使用第三方工具

已知公式 : 耗電量 = 電流 * 時間
例:平均電流爲150mA,測試時間30min,則,30min內耗電量爲:150 * 30 /60=75mAh(毫安小時)。
經過耗電量和使用手機電量的百分比,可得出手機電池容量(理論值)。
一個系統走一遍基礎功能耗電不該超過20%。
sql

 一、Emmageeshell

https://github.com/NetEase/Emmagee數據庫


Emmagee是網易杭州研究院QA團隊開發的一個簡單易上手的Android性能監測小工具,主要用於監控單個App的CPU,內存,流量,啓動耗時,電量,電流等性能狀態的變化,且用戶可自定義配置監控的頻率以及性能的實時顯示,並最終生成一份性能統計文件。json

二、騰訊GT瀏覽器

http://gt.tencent.com/download.html

此apk是一款能夠對APP進行測試的軟件,能夠在任何狀況下快速測試手機app的CPU、內存、流量、電量、幀率/流暢度等性能測試。
使用方法:

打開GT,點擊選擇被測應用,選中本身要測的app,選擇關注的測試點,cup、net(流量)、內存(pss)等,點擊「啓動」,在gt的插件標籤裏有耗電測試,導出文件查看電量使用。




3、其餘各類常見耗電量監控工具

金山電池醫生:可以記錄CPU耗時、流量消耗隨時間的變化曲線,這樣能夠查看app耗電在哪些時間點.
GSam Battery Pro耗電量信息顯示詳細,包括了喚醒鎖數,先後臺佔用cpu的時間,能夠導出數據,支持多種監控起始時間點設置
PowerTutor1.顯示系統電量消耗水平,記錄耗電量的焦耳值,不是百分比,包括LCD/OLED,CPU,WiFi,3G,GPS和Audio;2.查看某段時間內全部運行中的應用程序的耗電量
Battery Monitor Widget高度可定製化的電量監控小工具,不只能夠顯示當前電量,估算剩餘電量支撐時間,還能夠一目瞭然地檢測出各個APP的耗電歷史,從而方便進行比較。
Smart Battery Monitor:除了能夠在狀態欄顯示電池消耗百分比外,還能夠顯示電池的溫度,以及已充電時間。
Battery Indicator:亮點是輕便、小巧,甚至使用它時不會消耗電池。固然,它能夠顯示電池的電量百分比、電池的溫度、以及電池的健康信息。
Battery Widget:這個工具不只是一個電池Widget,還能夠做爲顯示選項,GPS,WiFi,藍牙選項等的快捷方式。
Battery Saver:被稱爲管理電池的最強大應用之一。除了顯示電量信息,電池溫度和健康信息外,它還能夠快速管理一些耗電量大的應用如:GPS,WiFi,藍牙等。另外:該工具能夠查看一天以內的哪一個時間點電池的耗電量最大。|
等等等等


方法3——Battery Historian

Android框架層經過一個名爲batterystats的系統服務,電池的信息,電壓,溫度,充電狀態等等,都是由BatteryService來提供的。電池的這些信息是BatteryService經過廣播主動把數據傳送給所關心的應用程序。實現了電量統計的功能,batterystats實現原理能夠查閱電量統計服務
Android
提供的dumpsys命令用於查看系統服務的信息(實現原理能夠查閱dumpsys介紹), 將batterystats做爲參數,就能輸出完整的電量統計信息。

執行:

手機鏈接usb執行:

adb shell dumpsys batterystats --enable full-wake-history 
adb shell dumpsys batterystats –reset //清空電池的歷史狀態

斷開USB,打開目標應用,執行monkey,正常使用5分鐘左右。

鏈接USB,執行:

adb bugreport > bugreport.txt
也能夠用adb shell dumpsys batterystats > com.nt.topline > toplinepower1.txt //獲得指定app相關的電量消耗信息。
python historian.py -a bugreport.txt > batterystats.html

上面的historian.py腳本是python寫的,因此須要python環境,從github上下載這個腳本。Chrome瀏覽器打開生成的battery.html文件,打開查看。


 

html中信息都能從bugreport.txt中找到相應的信息。 

分析各個指標表明的意義:

上面的10,20表明的就是秒的意思,它是以一分鐘爲週期,到第60秒的時候變爲0。橫座標就是一個時間範圍,我們的例子中統計的數據是以重置爲起點,獲取bugreport內容時刻爲終點。咱們一共採集了多長時間的數據,圖表下也有信息說明。(經其餘人的反饋,這個座標間隔是會隨着時間的長度發生改變,因此要以你的實際狀況爲準)
battery_level:電量,能夠看出電量的變化。好比上圖中的數據顯示剛開始電量是100%,而後在第11秒-12秒中間的某個時刻降到了99%。

plugged: 充電狀態,這一欄顯示是否進行了充電,以及充電的時間範圍。例如上圖反映了咱們在第22s插入了數據線,而後一直持續了數據採集結束。
screen: 屏幕是否點亮,這一點能夠考慮到睡眠狀態和點亮狀態下電量的使用信息。
top:該欄顯示當前時刻哪一個app處於最上層,就是當前手機運行的app,用來判斷某個app對手機電量的影響,這樣也能判斷出該app的耗電量信息。該欄記錄了應用在某一個時刻啓動,以及運行的時間,這對咱們比對不一樣應用對性能的影響有很大的幫助。
wake_lock*: wake_lock 該屬性是記錄wake_lock模塊的工做時間。是否有中止的時候等。Android的休眠喚醒主要基於wake_lock機制,只要系統中存在任一有效的wake_lock,系統就不能進入深度休眠,但能夠進行設備的淺度休眠操做。wake_lock通常在關閉lcd、tp但系統仍然須要正常運行的狀況下使用,好比聽歌、傳輸很大的文件等。
running:界面的狀態,主要判斷是否處於idle的狀態。用來判斷無操做狀態下電量的消耗。
wake_lock_in:wake_lock有不一樣的組件,這個地方記錄在某一個時刻,有哪些部件開始工做,以及工做的時間。
data_conn:數據鏈接方式的改變,上面的edge是說明採用的gprs的方式鏈接網絡的。此數據能夠看出手機是使用2g,3g,4g仍是wifi進行數據交換的。這一欄能夠看出不一樣的鏈接方式對電量使用的影響。
status:電池狀態信息,有充電,放電,未充電,已充滿,未知等不一樣狀態。 這一欄記錄了電池狀態的改變信息。
phone_signal_strength:手機信號狀態的改變。 這一欄記錄手機信號的強弱變化圖,依次來判斷手機信號對電量的影響。
health:電池健康狀態的信息,這個信息必定程度上反映了這塊電池使用了多長時間。 這一欄記錄電池狀態在什麼時候發生改變,上面的圖中電池狀態一直處於good狀態。
plug:充電方式,usb或者插座,以及顯示鏈接的時間。 這一欄顯示了不一樣的充電方式對電量使用的影響。
gps:gps是否開啓
phone_in_call :是否進行通話
Sync :是否跟後臺同步,能夠把鼠標停在某一項上面。能夠看到什麼時候sync同步 啓動的,持續時間Duration多久。電池容量不會顯示單一行爲消耗的具體電量,這裏只能顯示使用電池的頻率和時長,你能夠看分時段的剩餘電量來了解具體消耗了多少電量。 

Job :後臺的工做,好比服務service的運行。從下面圖中能夠看到qihoo的AppStore和魯大師都在運行後臺服務。 

data_conn:數據鏈接方式的改變,上面的edge是說明採用的gprs的方式鏈接網絡的。此數據能夠看出手機是使用2g,3g,4g仍是wifi進行數據交換的。這一欄能夠看出不一樣的鏈接方式對電量使用的影響。
status :電池狀態信息,有充電,放電,未充電,已充滿,未知等不一樣狀態。 這一欄記錄了電池狀態的改變信息。
phone_signal_strength :手機信號狀態的改變。 這一欄記錄手機信號的強弱變化圖,依次來判斷手機信號對電量的影響。

結果分析:

經過前面學習到的Battery Historian咱們能夠獲得設備的電量消耗數據.
例如拿移動網絡舉例,若是數據中的移動蜂窩網絡(Mobile Radio)電量消耗呈現下面的狀況,間隔很小,又頻繁斷斷續續的出現,說明電量消耗性能很很差:

通過優化以後,若是呈現下面的圖示,說明電量消耗的性能是良好的:

另外WiFi鏈接下,網絡傳輸的電量消耗要比移動網絡少不少,應該儘可能減小移動網絡下的數據傳輸,多在WiFi環境下傳輸數據。

耗電緣由分析

主要形成耗電的幾大緣由:

  • 屏幕喚醒

  • CPU喚醒

  • 蜂窩數據

  • 傳感器

    可能形成耗電的緣由


    • 網絡請求耗電,並且手機數據網絡進行http請求比無線網進行http請求更加耗電,由於數據網絡調用到一些底層的硬件模塊,就如GPS同樣,當手機打開GPS功能後,也是啓動了一些硬件模塊就會明顯增長耗電

    • 高頻的刷新UI界面,刷新UI界面其實就是進行layout的繪製,若是一個Activity的佈局嵌套太多層,那麼每一層layout都會刷新一次,例如動畫等等這些都會形成耗電

    • 數據庫,SD卡文件操做,這些都是屬於耗時操做,當操做次數不多的時候基本不會有耗電問題,可是當短期內操做次數不少的話,也會明顯的增長耗電,同時也有可能形成頁面卡頓

    • AlarmManager,例如一些推送的心跳包實現,AlarmManager會定時喚醒CPU去執行一些任務,也是形成耗電的一大源頭

    • 手機網絡環境很差的時候會頻繁的切換網絡,由於網絡數據交互的時候,系統也是會被喚醒的,因此APP若是在監聽了網絡切換廣播後作了大量的操做,同樣會增長耗電

    • 針對一些任務隊列的處理,若是隊列堆積的任務太多,致使循環執行過久也會形成耗電,由於佔用了CPU資源去執行代碼,咱們的log日誌工具保存到文件就是用任務隊列實現的,當壓力測試SDK一次性接受1萬條消息的時候,那內存就表上來了,跟了下發現日誌保存隊列裏面積壓了4千多個任務,這時候即便手機鎖屏,也還會不斷的把隊列中的任務執行完而後CPU纔會休眠下去的,一樣會形成嚴重的耗電,耗內存,好在release版本的日誌都是關閉的

    • 執行一些高運算量的代碼,例如json數據解析,一些二進制協議的數據編碼和解碼

    • 接收系統的一分鐘廣播,而後作一些程序邏輯處理,其實接收一分鐘廣播不耗電,耗電的是一分鐘執行一次程序處理

    • Wake Lock使用不當致使沒有及時的釋放,Wake Lock能夠阻止cpu進入休眠的,若是沒有及時的release會形成cpu沒法休眠,程序耗電嚴重

    • 若是程序中有定時任務,在cpu休眠以後,定時任務就會被掛起不執行,這時候並不會形成太大的耗電,可是若是這個定時任務的時間間隔很短,1秒執行一次,那麼當手機app集成了推送,推送就會有心跳包經過AlarmManager來喚醒,每次喚醒的時候就會再去執行掛起的定時任務,雖然執行定時任務的耗電量可能比心跳包的耗電量少不少,不過仍是須要注意的,聚沙成塔

    • 其實android中的Log日誌的打印也會耗電的,在平常開發中,咱們可能不只會把log打印到AndroidStudio裏面,有可能還會保存起來,並且可能在打印對象信息數據的時候會用到json格式轉換,這些都會增長耗電,可是在正式發佈的apk包中日誌管理通常都是關閉的

    • 在手機鎖屏後,CPU會過一段時間才休眠,若是程序中有定時任務,在CPU休眠後會被掛起不執行,可是在CPU休眠以前,定時任務仍是會一直的執行的,以前遇到過這麼一個問題,咱們採用Picasso庫:Picasso.with(context)


      

    優化建議:

    針對主要耗電緣由的優化:

      o   傳感器的使用,好比gps,若是業務上非頻繁使用而且要求精度不高,那麼就在業務上優化定位時機和精度.
      o   若是業務上須要有長時間的service,那麼要考慮到CPU weak lock,防止後臺任務沒有完成,可是cpu睡眠,或者任務已經完成,仍然持有weak lock
      o   咱們也許會在手機充電時,作一些日誌上傳操做的定時任務,那麼注意重試次數和成功後處理,防止用戶一晚上充電不到80%,而後手機廠商爲咱們背鍋的狀況
      o   已知屏幕喚醒是耗電大戶,緣由是屏幕渲染,繪製消耗資源,因此咱們在自定義視圖,佈局的時候,要儘可能作到Android性能優化裏要求
      o   同理,各類優化,平時編碼的習慣,都會影響咱們脆弱的電量
      o   爲了減小電量的消耗,在蜂窩移動網絡下,最好作到批量執行網絡請求,儘可能避免頻繁的間隔網絡請求。


    針對Http請求優化: 

      o    對http請求數據作GZIP壓縮,當前流行的http第三方看默認都支持GZIP壓縮
     o    Http緩存,Http協議有一個Cache機制,當發出http請求的時候會先到指定目錄下檢查是否已經存在這個請求的數據,若是存在而且還沒過期,那麼就會直接返回;而一些第三方例如OkHttp也有有本身的緩存    機制OKHTTP緩存
      o    合併Http請求來減小Http請求次數,由於Http底層也是TCP鏈接,對於每一個Http請求,發出請求的時候都會建立TCP鏈接,請求結束後會斷開TCP鏈接,那麼當Http請求次數不少的時候就會頻繁的建立和斷開TCP鏈接,若是把當中一些請求進行合理的合併,那麼就會減小Http請求次數
      o    制定合理的Http請求數據格式和返回數據格式,作到請求數據中沒有冗餘字
      o    能夠在Http請求數據格式裏面加一個字段dataVersion表明本地已有數據的版本號,而後傳到服務器,服務器的數據表中也有一個字段是dataVersion,當服務器數據被修改的時候,dataVersion就加一,當檢測到客戶端傳上來的dataVersion小於服務器數據表中的dataVersion的時候就返回最新數據,不然能夠直接返回空數據表明當前本地數據已是最新數據,這樣就不會每次請求http的時候都會返回大量數據,當數據沒有被改變的時候直接返回空,減小了http請求過程當中的數據交互(可是要考慮一點,只有一些請求數據量比較大的才適合,由於增長了dataVersion字段後不管給客戶端仍是服務端也都相應的增長了維護的成本)


    針對數據庫,SD卡文件操做: 

    o  APP在對數據庫或者SD卡文件操做的時候無非也是涉及到一些數據的轉換,json轉換,能夠採用json解析效率高的第三方庫,例如fast json,Jackson,gson
    o   能夠把一些須要持久化到數據庫或者文件中的數據先緩存在內存中,而後在一個時間點一塊兒觸發一同更新到數據庫或者文件中;例如,在進入Activity的時候會首先從數據庫中搜索出賬戶信息而且展現在界面,而後會再去發Http請求服務器的賬戶信息數據,再把服務器最新的賬戶信息數據刷新到界面中,同時也存在一個內存對象中,這時候先不更新到數據庫,當退出這個Activity界面的時候能夠去檢測賬戶數據是否發生改變,若是改變了就更新到數據中;這麼作的好處是:若是在Activity界面屢次修改數據,那最新的數據都是隻更新到內存中的,當Activity退出後才把最新的賬戶信息數據更新到數據庫中,不必更改一次就同時把數據更新一次到數據庫
    o    SD卡的文件讀寫操做比數據庫要快,數據庫也是屬於文件,可是在寫數據的時候還要通過sqlite的一些列數據庫操做,可是SD卡在寫數據的時候是直接寫到文件中的,因此針對與簡單數據,標誌變量或者數據條數不多的數據,並且安全性要求也不高的數據能夠直接存在文件中,例如SharedPreferences中,只有關係型的數據,數據安全性較高的,數據記錄條數比較多的能夠選擇數據庫存儲,並且若是數據庫進行加密後,對於數據庫的讀寫操做會更慢了
    o    針對數據庫操做盡可能不要直接使用android裏面的Sqlite來手寫讀寫的那些sql語句,能夠選擇一些orm框架庫,例如ormlite,GreenDao等等,咱們選擇的是ormlite,由於ormlite數據庫加密已經有現成的庫能夠提供使用。


    以上!感謝!分析不夠全面的部分歡迎交流補充!

    參考:

    http://blog.csdn.net/itfootball/article/details/44084159
    http://blog.csdn.net/itfootball/article/details/49004699
    http://news.mydrivers.com/1/282/282933.htm
    https://github.com/google/battery-historian
    http://hukai.me/android-performance-battery/
    https://juejin.im/entry/589d66c686b599006b2e07a8
    http://xusx1024.com/2018/01/08/battery-historian-2/
    http://gityuan.com/2016/01/10/power_rank/
    http://hukai.me/android-performance-patterns/
    http://duanqz.github.io/2015-07-21-batterystats-part1
    http://duanqz.github.io/2015-07-19-Intro-to-dumpsys


    免費領取驗證碼、內容安全、短信發送、直播點播體驗包及雲服務器等套餐

    更多網易技術、產品、運營經驗分享請訪問網易雲社區


    相關文章:
    【推薦】 用Go編寫的本地文件服務器

    相關文章
    相關標籤/搜索