美團技術專欄: 關注MAYOU18
美團測試團隊負責App的質量保證工做,平常除了App的功能測試之外,還會重點關注App的性能測試。如今你們對手機愈來愈依賴,而上面各App的耗電量,直接影響了手機的待機時間,是用戶很是關心的一點。本文主要經過一個典型案例,介紹App性能測試中的電量測試,並總結了咱們由此引起的一些思考。html
短視頻做爲已被市場驗證的新內容傳播載體,能有效增長用戶停留時長。大衆點評App從9.3版本開始推出短視頻相關內容,在各頁面新增了短視頻模塊。在短視頻功能測試中,咱們發現若是在視頻列表頁中播放視頻,手機很快就會發燙。針對這種現象,咱們立刻拉取數據進行了分析,測試數據代表,視頻列表頁耗電量居然是詳情頁的11倍。這是怎麼回事兒呢?
目前行業內有不少電量測試的方法,咱們採用的是Battery Historian,這是Google推出的一款Android系統電量分析工具,支持5.0(API 21)及以上系統手機的電量分析。java
短視頻主要包括三個核心頁面:視頻列表頁、視頻詳情頁、做者頁,本次的測試對象就是這三個頁面。算法
測試機型:華爲Mate 9 Android 7.0
電池容量:4000mAh
播放的視頻時長:1min15s
測試場景設計:WiFi環境下,打開App,播放視頻,經過點擊「從新播放」,連續播放10次
對比場景:停在App首頁20min,手機不滅屏
注意:測試過程不充電,每次測試環境一致小程序
以下是Battery Historian測試結果部分截圖:微信小程序
視頻列表頁微信
視頻詳情頁ide
對測試結果數據進行彙總整理:函數
消耗電量:系統總電量的佔比
從測試結果能夠看到,短視頻列表頁耗電量特別高,是視頻詳情頁的11倍。工具
視頻列表頁消耗電量太高,從測試數據能夠很明顯的看出來,視頻列表頁CPU佔用時間高不少。從播放器佈局來看,列表頁和做者頁比視頻詳情頁只是多出了動畫音符。以下圖,紅框中圈出的視頻左下角的音符。佈局
電量消耗差別這麼大,是否跟動畫音符有關呢。爲了排除這個問題,從新編譯了一個去掉動畫音符的APK進行測試。測試結果:
從測試結果來看,CPU和耗電量很明顯都降低了不少,所以肯定是動畫音符引發的。打開GPU視圖更新的開關,查看三個頁面的繪製狀況。打開視頻列表頁,能夠看到,動畫音符每波動一次,會致使整個頁面都在不停的繪製。以下是視頻列表頁繪製的狀況:
從動圖能夠很明顯看出該頁面繪製十分異常,動畫音符每波動一次,會致使整個頁面都從新繪製一遍。
因此,到這裏就明白了問題的緣由,由於頁面上動畫音符的實現方式有問題,動畫音符波動時,致使整個頁面會跟着一塊兒不停的從新繪製。而頁面的重複繪製,會使App CPU佔用比正常狀況下高出不少,進而致使耗電量高。
定位到緣由以後,開發針對性的進行了修復。動畫音符柱狀圖的實現,以前設計由多個可變化的單柱形View組成,單個柱形View重寫了onMeasure & OnDraw方法,從外部柱狀圖View中初始化單個柱子的高度,而後自動根據一個函數式來變化高度。由於每次都須要層層調用Measure和對應的Layout,因此形成外層控件的屢次layout,進而形成CPU佔用率增大。修復以後,使用另外一種方式實現,只重寫了View的OnDraw方法,每次使用Canvas畫出全部柱狀圖,使用ValueAnimator來計算變化柱狀圖高度,也再也不影響父控件的Layout。以下是修復先後的核心代碼:
修復以後動畫音符波動時的繪製區域:
修復以後,從新使用Battery Historian進行驗證,測試結果:
從上面的測試結果,能夠看到,視頻列表頁和做者頁,耗電狀況獲得明顯的優化。
總結一下,短視頻耗電量的問題,是因爲錯誤的繪製方法,致使CPU佔用太高,進而致使耗電量高。那麼由於動畫音符致使耗電量異常的問題到這裏就完美的解決了。CPU負載高,會致使耗電量高是顯而易見的。可是還想深刻探索一下,在手機系統各App耗電量排行榜中,耗電量是怎麼計算的?還有哪些因素會影響耗電量呢?帶着這些疑問,咱們來看看系統計算耗電量的原理。
根據物理學中的知識,功=電壓*電流*時間,可是一部手機中,電壓值U正常來講是不會變的,因此能夠忽略,只經過電流和時間就能夠表示電量。模塊電量(mAh)=模塊電流(mA)*模塊耗時(h)。模塊耗時比較容易理解,可是模塊電流怎樣獲取呢,不一樣廠商的手機,硬件不一樣,是否會影響模塊的電流呢。看一下系統提供的接口:./frameworks/base/core/java/com/Android/internal/os/PowerProfile.java
該類提供了public double getAveragePower(String type)接口,type可取PowerProfile中定義的常量值,包括POWER_CPU_IDLE(CPU空閒時),POWER_CPU_ACTIVE(CPU處於活動時),POWER_WIFI_ON(WiFi開啓時)等各類狀態。而且從接口能夠看出來,每一個模塊的電流值,是從power_profile.xml文件取的值。PowerProfile.java只是用於讀取power_profile.xml的接口而已,後者纔是存儲系統耗電信息的核心文件。power_profile.xml文件的存放路徑是/system/framework/framework-res.apk。
以Nexus 6P爲例,在該路徑獲取到framework-res.apk文件。使用apktool,對framework-res.apk進行反解析,獲取到手機裏面的power_profile.xml文件,內容以下所示:
<?xml version="1.0" encoding="utf-8"?> <device name="Android"> <item name="none">0</item> <item name="screen.on">169.4278765</item> <item name="screen.full">79.09344216</item> <item name="bluetooth.active">25.2</item> <item name="bluetooth.on">1.7</item> <item name="wifi.on">21.21733311</item> <item name="wifi.active">98.04989804</item> <item name="wifi.scan">129.8951166</item> <item name="dsp.audio">26.5</item> <item name="dsp.video">242.0</item> <item name="gps.on">5.661105191</item> <item name="radio.active">64.8918361</item> <item name="radio.scanning">19.13559783</item> <array name="radio.on"> <value>17.52231575</value> <value>5.902211798</value> <value>6.454893079</value> <value>6.771166916</value> <value>6.725541238</value> </array> <array name="cpu.speeds.cluster0"> <value>384000</value> <value>460800</value> <value>600000</value> <value>672000</value> <value>768000</value> <value>864000</value> <value>960000</value> <value>1248000</value> <value>1344000</value> <value>1478400</value> <value>1555200</value> </array> <array name="cpu.speeds.cluster1"> <value>384000</value> <value>480000</value> <value>633600</value> <value>768000</value> <value>864000</value> <value>960000</value> <value>1248000</value> <value>1344000</value> <value>1440000</value> <value>1536000</value> <value>1632000</value> <value>1728000</value> <value>1824000</value> <value>1958400</value> </array> <item name="cpu.idle">0.144925583</item> <item name="cpu.awake">9.488210416</item> <array name="cpu.active.cluster0"> <value>202.17</value> <value>211.34</value> <value>224.22</value> <value>238.72</value> <value>251.89</value> <value>263.07</value> <value>276.33</value> <value>314.40</value> <value>328.12</value> <value>369.63</value> <value>391.05</value> </array> <array name="cpu.active.cluster1"> <value>354.95</value> <value>387.15</value> <value>442.86</value> <value>510.20</value> <value>582.65</value> <value>631.99</value> <value>812.02</value> <value>858.84</value> <value>943.23</value> <value>992.45</value> <value>1086.32</value> <value>1151.96</value> <value>1253.80</value> <value>1397.67</value> </array> <array name="cpu.clusters.cores"> <value>4</value> <value>4</value> </array> <item name="battery.capacity">3450</item> <array name="wifi.batchedscan"> <value>.0003</value> <value>.003</value> <value>.03</value> <value>.3</value> <value>3</value> </array> </device>
從文件內容中能夠看到,power_profile.xml文件中,定義了消耗電量的各模塊。以下圖所示:
文件中定義了該手機各耗電模塊在不一樣狀態下的電流值。剛剛提到,電量只跟電流值和時間相關,因此經過這個文件,再加上模塊的耗時,就能夠計算出App消耗的電量,App電量=∑App模塊電量。劃重點,手機系統裏面的電量排行,也是根據這個原理計算的。
瞭解原理對於日常在App耗電量的測試有很大的幫助。由於獲取到手機power_profile.xml文件,就能夠清楚的知道這個手機上,哪些模塊會耗電,以及哪些模塊在什麼狀態下耗電量最高。那麼測試的時候,應該重點關注調用了這些模塊的地方。好比App在哪些地方使用WiFi、藍牙、GPS等等。
例如最近對比測試其餘App發現,在一些特定的場景下,該App置於前臺20min內,掃描了WiFi 50次,這種異常會致使App耗電量大大增長。而且反過來,當有case報App耗電量異常時,也能夠從這些點去考慮,幫助定位問題。
如上,列出的一些經常使用的電量測試方法。綜合各方法的優缺點,在定製個性化電量測試工具以前,目前採用的方法是Battery Historian。目前行業內,App耗電測試有不少種方案,若是僅僅測試出一個總體的電量值,對於定位問題是遠遠不夠的。藉助Battery Historian,能夠查看自設備上次充滿電以來各類彙總統計信息,而且能夠選擇一個App查看詳細信息。因此QA的測試結果反饋從「這個版本App耗電量」高,變成「這個版本CPU佔用高」「這個版本WiFi掃描異常」,能夠幫助更快的定位到問題緣由及解決問題。
固然,除了測試方法和測試工具,測試場景設計也很是重要。若是是在App內毫無規律的瀏覽,即便發現頁面有問題,有很難定位到是哪一個模塊的問題。因此要針對性的設計場景,而且進行一些場景的對比,找出差別的地方。
本文主要經過一個案例,介紹關於App電量測試中使用的一些基本方法和思路。電量測試採用的Battery Historian方法,雖然能初步解決問題,可是在實際的應用場景中還存在不少不足。目前美團雲測平臺,已經集成了電量測試方法,經過自動化操做,獲取電量測試文件並進行解析,極大的提升了測試效率。目前每一個版本發佈以前,咱們都會進行專門的電量測試,保障用戶的使用體驗。在電量測試方面,美團測試團隊還在持續的實踐和優化中。
倩雲,美團客戶端測試開發工程師,2015年加入美團,主要負責大衆點評App基礎功能及Android專項測試工做。
點評平臺技術部-平臺質量中心,Base上海,主要負責大衆點評平臺入口和基礎功能的質量保障。平臺包括大衆點評App、大衆點評微信小程序、PC站:www.dianping.com、M站:m.dianping.com;主要業務涵蓋:帳號、POI、評價、視頻、文章、會員社區、問答、運營活動、搜索推薦、通訊鏈路、運營活動等基礎業務。熱忱期待各位QA、開發、算法人才加入點評平臺技術部。聯繫郵箱:wanxia.wang#dianping.com。