在智能手機App競爭愈來愈激烈的今天,Android App各項性能如CPU、內存消耗等都是咱們在開發測試中須要關注的指標,如何將App打造得更加「優雅」是咱們須要不斷追求探索的方向,下面咱們從內存 和流暢度兩個緯度來講說如何對Android App進行評測和調優。html
內存不是無限使用的,若是內存過大或泄漏會出現OOM(Out Of Memory)、UI不流暢等問題,所以內存也是一個稀缺資源,咱們應該保證沒有內存泄漏且對不須要使用的內存及時釋放。通常內存測試或分析內存問題能夠分爲下面幾步:算法
測試分析內存有如下幾種方法:swift
Heap查看堆的分配狀況:瀏覽器
主要關注兩項數據:多線程
1)Heap Size堆的大小,當資源增長,當前堆的空餘空間不夠時,系統會增長堆的大小。
2)Allocated堆中已分配的大小,這是應用程序實際佔用的內存大小,資源回收後,此項數據會變小。工具
注:若是進行反覆操做,或堆的大小一直增長,則有內存泄漏的隱患。
Allocation Tracker跟蹤內存分配狀況:oop
Leak Suspects:內存泄露報告
Top Components:吃貨報告
Histogram:每一個Class佔用內存
Dominator Tree:列出哪些對象佔用內存最多以及誰hold住這些對象性能
Android常見的內存問題有:測試
下面就是一個例子,static變量佔用過大的內存比例(7.1M),這裏碰到該狀況須要具體分析裏面數據是否都是須要常駐的,不要把不少不相干的變量設爲static屬性。網站
這裏須要本身搜索代碼查看是哪裏一直hold住了資源致使沒有釋放。
圖上能夠看到Bitmap佔用內存很大(5.7M),利用MAT來找到他的outgoing和incoming引用:
能夠找到這塊內存的引用關係,而後找代碼。
在遇到圖片資源佔用過大的狀況,建議:
1)及時的銷燬;
2)設置必定的採樣率;
3)巧妙的運用軟引用(SoftRefrence)。
Cursor用完記得關掉,若是實在不肯定Cursor是否關閉,能夠在onDestroy中關了。
總的來講,沒有嚴格意義上泄露只是你hold過久。2、流暢度
對於App是否流暢這個維度,以前一直沒有一個客觀的數據來將用戶客觀感覺和數據一一對應起來。雖然以前有FPS(每秒幀數)這個指標來衡量,不過 這對於App這樣的大部分時候可能沒有界面更新的軟件來講,是一個不恰當的客觀數據(固然FPS用於遊戲或視頻類業務確定是沒問題的)。在和咱們的瀏覽器 團隊溝通後,應他們的需求(它不只要作最快的瀏覽器,同時也要作最流暢的瀏覽器),MIG(專項測試組)多位同窗一塊兒來經過研究Android自身UI更 新機制以及經過數學建模摸索出一個客觀數據指標流暢度(SM: SMoothness)來量化流暢度這個客觀感覺。
首先從下面開始…
關於Android是如何去更新UI的,我相信有不少文章來介紹其中步驟以及過程,大致上能夠用下圖來展現:
從圖中能夠看到,不管哪條路走下去始終都由SurfaceFlinger來控制最後更新。在Android版本更新過程當中發如今Jelly Bean版本更新中,Google加入一個Project Butter來解決嚴重影響Android口碑問題之一的UI流暢性差的問題。而Project Butter中引入了三個核心元素,即VSync(垂直同步)、Triple Buffer和Choreographer。
在Android 4.1(JB)中引入了VSync機制,是Vertical Synchronization(垂直同步)的縮寫,是一種在PC上已經很早就普遍使用的技術,能夠簡單地把它認爲是一種定時中斷。
如上圖所示在VSync機制下的繪製過程。從上面的圖看CPU和GPU處理時間都很快都少於一個VSync的間隔也就是16ms,而且每一個間隔都有繪製的狀況下那麼當前的FPS便是60幀。當CPU和GPU處理時間都很慢或者由於其餘的緣由,好比在主線程中幹活太多那麼就會出現以下圖這樣的情況。
從上圖能夠看到CPU和GPU處理時間由於各類緣由比較慢都大於一個VSync的間隔(16ms),那麼能夠看到在第二個VSync還在處理A區域 的繪製這樣就不可能實現理論上的FPS 60了同時也出現了丟幀(SF: Skipped Frame)。上圖爲了便於理解用的是雙Buffer機制的狀況,實際上Android 4.1在引入了Triple Buffer,因此當雙Buffer不夠用時Triple Buffer丟幀的狀況以下圖所示。
Oh my ladygaga~~~這些把灑家看暈了…那打個比方講得通俗點。
VSync 機制就像是一臺轉速固定的發動機(60轉/s)。它每一轉帶動着去作一些UI相關的事情,可是不是每一轉都會有工做去作(就像有時在空擋,有時在D檔)。 有時候由於各類阻力某一圈工做量比較重超過了16.6ms,那麼這臺發動機這秒內就不是60轉了,固然也有可能被其餘因素影響好比給油不足(主線程裏乾的 活太多)等等。就會出現轉速下降的情況咱們把這個轉速叫作流暢度。
實際上在咱們不少的Android App中,不多有須要不斷地去繪製的場景,不少時候都是靜態的。也就是會出 現這樣的情況,雖然1s中VSync的60個Loop中不是每一個都在作繪製的工做FPS比較低,但並不能表明這個時候程序不流暢(如我將App放在那不動 實測FPS爲1)。因此FPS爲1這個數並不能表明當前App在UI上界面不流暢,所以1s內VSync這個Loop運行了多少次更加能說明當前App的 流暢程度。So…另2個指標比FPS更加能表明當前的App是否處於流暢的狀態一樣這2個指標更加可以量化App卡頓的程度:
1)和丟幀相對1s內有60個Loop由於某幾回工做時間超過了16ms(丟幀),這樣Loop就沒法運行60次(理論最大值)。
2)當流暢度越小的時候說明當前程序越卡頓。
接着上面的結論若是在這樣的機制下每次Loop運行以前通知我下,我就記個數就行了。
很幸運咱們在新的Android的那一套機制中找到了一個畫圖的打雜工Choreographer這個對象。根據Google的官方API文檔描述 他是用來協調animations、input以及drawing時序的,而且每一個Looper共用一個Choreographer對象。
Choreographer的定義和結構:
1) 固定每隔16.6ms執行一次(這個值是一個靜態變量會根據系統版本不一樣而採不一樣的值,目前測試版本是16.6ms這樣最高的刷新的幀率就控制在60FPS之內);
2) 若是沒有以上事件的時候一樣也會運行這樣一個Loop;
3) 因此這個Loop在1s以內運行了多少次,便可以表示當前App繪製的最高的能力,也就是Android App卡頓的程度…
4) 另,在一次Loop時若是執行時間超過了16.6ms,那麼多於16.6ms的時間除以16.6ms,便是當前App的丟幀(SF: Skipped Frame)。
採用這樣方式就能夠在App內部觀測當前App的流暢度。固然,還有更簡單的方法,採用GT工具獲取流暢度,見下面步驟說明。
1)打開被測App,而後打開GT在插件中選擇GT Injector:
2)選擇被測進程&點擊射它:
3)注入成功後Para界面會出現流暢度指標以及被插入程序的CPU佔有率這些而且會帶上被插入的進程名。將流暢度後面小方框勾選(代表記錄SM值到log文件),而後點擊Gather & Warning下小紅圈(代表開始記錄數值)。
4)開始作相關的測試測試。
5)完成測試後在剛纔的界面點擊流暢度(SM)出現下列界面,而後點擊磁盤圖標,保存log到指定名字的文件夾。
6)最後利用各類工具(好比應用寶)把log導入到PC端進行後期處理(文件保存在SD卡/GT/GW/進程名/自定義文件夾名下)。
注:以上的操做由於涉及到進程注入須要手機Root權限,若是不能使用能夠郵件給我,地址見文章末尾處。
因此,咱們拿a、b、c三個瀏覽器爲例,對比評測下這樣的數據和人感覺是否對應得上。首先,咱們爲了把感官和人的感覺對應上特把主動感官分數對應到如下幾種描述以下表:
場景1. 瀏覽妹子圖……看看流暢度(SM)和丟幀(SF)之間關係
來看看流暢度(SM)和丟幀(SF)之間關係…這個數據是用瀏覽器瀏覽妹子圖時採集。由於丟幀是個不連續的過程,因此後面的圖中丟幀都是以點來表示其離散的狀態。
從上面圖能夠看出:
從這個數據能夠看到丟幀(SF)越多流暢度(SM)越低,而且主觀感受是比較卡的(界面滑動明顯頓挫感,響應用戶輸入有種慢半拍的感受)。
場景2. 看妹子圖……引入FPS看看這3者關係…
一樣這段看妹子的過程當中主觀感覺也是在2.5分:
這個數據裏面引入了FPS數據。從上圖能夠看出:
1)流暢度很高FPS比較低,無丟幀狀況…當時靜置在某個界面沒有動此時主觀評分應該在4.5左右;
2)FPS比較高,丟幀很嚴重流暢度很低…當時在不斷刷新不少圖片出來主觀評分應該在2.0如下。
把這2部分數據放大看:
流暢度很高FPS比較低無丟幀:
本場景數據統計:
這個局部場景雖然畫面一直在動,沒有丟幀FPS在20如下可是流暢度比較高。So…從次場景能夠看出這樣流暢度SM比FPS更加適合來客觀描述Android App卡的程度。
從上面能夠看出數據量比較大並且幾個產品條曲線之間有交錯那如何評定哪一個在某些場景下更好呢?因而咱們就想:經過SM數據判斷App流暢狀況,並給出一個定量的結果。
思路:
流暢度評估方法:
1. 預處理,每5個(秒)一組,取最低值。若是5秒內出現多於一次卡頓(SM低於40),則再乘以一個和卡頓次數有關的權值(小於1)。說明:若是卡頓出現次 數較少,平均值和方差不容易發現問題。所以沒有直接對數據評估,先進行了預處理,突出SM值低的部分,加大卡頓對總分的影響。
處理前三組數據:
處理後三組數據:
2. 將處理後的數據按卡頓和流暢分段,針對每段打分。說明:若是隻有最後總分,且流暢的時間較長,卡頓的數據容易被流暢的數據淹沒。並且有些測試場景存在一段 流暢,一段卡頓的現象,卡頓並不必定在整個測試過程當中存在。這樣分開流暢和卡頓的區間處 理,更容易看出卡頓的程度。
3. 根據測試經驗,對SM值對應的卡頓嚴重程度打分。說明:根據測試同窗的經驗,流暢度指標SM低於40時,用戶能感知到卡頓,SM在20如下卡頓比較嚴重。 所以在打分時,SM值在20如下時打分最低,對應0-20,在20-30區間打分低,對應20-60,30-40區間打 分較低,對應60-70,40以上打分在70以上。
4. 整體打分時下降流暢區間的權重。說明:這樣處理的緣由和第一項的緣由同樣,咱們更關注的是卡頓,流暢區間過長時會淹沒卡頓的數據。
而後咱們拿同一個測試場景下的測試數據出來對比一下:
1)網頁滑動(Nexus 4上測試):
測試方法:打開某網站,來回上下滑動,在滑動的過程當中記錄流暢度數據。
流暢度評估數據:
從上面的數據能夠看出滑動瀏覽網頁的時候,其中c瀏覽器略微好於其餘兩個。固然這都是在性能比較好的手機(N4)上測試主觀感覺差距不大可是從量化數據上能夠看出優劣。評分差距就和主觀感覺拉開分值差很少能對應上,從客觀上能夠證實這套評分算法某種程度上的準確性。