1. 程式人生 > >Android移動客戶端效能測試淺談——電量

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

本文由作者張迎貞授權網易雲社群釋出。


APP效能測試除了需要監控PCU、記憶體佔用、流量等,還需要獲取APP的電量資料,測試在可接受範圍內,避免APP出現過度消耗電量的現象。
手機有很多硬體模組:CPU,藍芽,GPS,顯示屏,Wifi,射頻(Cellular Radio)等,在手機使用過程中,這些硬體模組可能處於不同的狀態,譬如WIFI開啟或關閉,螢幕是亮還是暗,CPU執行或休眠。 硬體模組在不同的狀態下的耗電量是不同的。Android在進行電量統計時,並不是採用直接記錄電流消耗量的方式,而是跟蹤硬體模組在不同狀態下的使用時間,收集一些可用資訊,用來近似的計算出電池消耗量。
從使用者使用層面來看,Android需要統計出應用程式的耗電量。應用程式的耗電量由很多部分組成,可能使用了GPS,藍芽等模組,可能應用程式要求長時間亮屏(譬如遊戲、視訊類應用)。 一個應用程式的電量統計,可以採用累計應用程式使用所有硬體模組時間這種方式近似計算出來。
舉一個例子,假定某個APP使用了GPS,使用時間用 t

 表示。GPS模組單位時間的耗電量用 w 表示,那麼,這個APK使用GPS的耗電量就可以按照如下方式計算:
耗電量 = 單位時間耗電量(w) × 使用時間(t)

測試方法多種多樣:

1、CPU空閒時,停留在主介面不退出,開啟網路然後鎖屏,12小時後檢視電量、流量變化
2、APP在操作執行時(此過程可藉助使用monkey進行壓力測試),1小時後檢視電量、流量變化
3、第三方APP進行步驟1、2相同的場景測試
4、對比競品APP的耗電量。
期望結果:APP在靜止狀態時無沒有明顯的耗電情況,在執行狀態時耗電量在可接受範圍內。

方法1——手機自帶

有的手機設定選單裡面會有流量和電量統計類,只需在測試前後記錄下電量值,便可獲取消耗電量數值。

 

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

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

 1、Emmagee

https://github.com/NetEase/Emmagee


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

2、騰訊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編寫的本地檔案伺服器