天天看點

Android應用性能評測調優

前言

在智能手機App競争越來越激烈的今天,Android App各項性能如CPU、記憶體消耗等都是我們在開發測試中需要關注的名額,如何将App打造得更加“優雅”是我們需要不斷追求探索的方向,下面我們從記憶體和流暢度兩個緯度來說說如何對Android App進行評測和調優。

一、記憶體

記憶體不是無限使用的,如果記憶體過大或洩漏會出現OOM(Out Of Memory)、UI不流暢等問題,是以記憶體也是一個稀缺資源,我們應該保證沒有記憶體洩漏且對不需要使用的記憶體及時釋放。一般記憶體測試或分析記憶體問題可以分為下面幾步:

  • 編譯代碼
  • 標明測試場景(來自于經驗&開發)
  • 測試場景轉換成用例
  • 跑起工具Run用例
  • 結合代碼,分析,分析…

1. 記憶體測試通用的方法

測試分析記憶體有以下幾種方法:

  • DDMS(Heap&Allocation Tracker)

Heap檢視堆的配置設定情況:

Android應用性能評測調優

主要關注兩項資料:

1)Heap Size堆的大小,當資源增加,目前堆的空餘空間不夠時,系統會增加堆的大小。 

2)Allocated堆中已配置設定的大小,這是應用程式實際占用的記憶體大小,資源回收後,此項資料會變小。

注:如果進行反複操作,或堆的大小一直增加,則有記憶體洩漏的隐患。

Allocation Tracker跟蹤記憶體配置設定情況:

Android應用性能評測調優
  • MAT(Memory Analyzer)

Leak Suspects:記憶體洩露報告 

Top Components:吃貨報告 

Histogram:每個Class占用記憶體 

Dominator Tree:列出哪些對象占用記憶體最多以及誰hold住這些對象

2. Android常見的記憶體問題

Android常見的記憶體問題有:

  • 萬惡的Static通常見到在單例模式

下面就是一個例子,static變量占用過大的記憶體比例(7.1M),這裡碰到該情況需要具體分析裡面資料是否都是需要常駐的,不要把很多不相幹的變量設為static屬性。

Android應用性能評測調優
  • 多線程生命周期過長hold住本該釋放資源

這裡需要自己搜尋代碼檢視是哪裡一直hold住了資源導緻沒有釋放。

  • 大胖子Bitmap
Android應用性能評測調優

圖上可以看到Bitmap占用記憶體很大(5.7M),利用MAT來找到他的outgoing和incoming引用:

Android應用性能評測調優

可以找到這塊記憶體的引用關系,然後找代碼。

Android應用性能評測調優

在遇到圖檔資源占用過大的情況,建議:

1)及時的銷毀;

2)設定一定的采樣率;

3)巧妙的運用軟引用(SoftRefrence)。

Android應用性能評測調優
  • Cursor

Cursor用完記得關掉,如果實在不确定Cursor是否關閉,可以在onDestroy中關了。

Android應用性能評測調優
總的來說,沒有嚴格意義上洩露隻是你hold太久。

二、流暢度

對于App是否流暢這個次元,之前一直沒有一個客觀的資料來将使用者客觀感受和資料一一對應起來。雖然之前有FPS(每秒幀數)這個名額來衡量,不過這對于App這樣的大部分時候可能沒有界面更新的軟體來說,是一個不恰當的客觀資料(當然FPS用于遊戲或視訊類業務肯定是沒問題的)。在和我們的浏覽器團隊溝通後,應他們的需求(它不僅要做最快的浏覽器,同時也要做最流暢的浏覽器),MIG(專項測試組)多位同學一起來通過研究Android自身UI更新機制以及通過數學模組化摸索出一個客觀資料名額流暢度(SM: SMoothness)來量化流暢度這個客觀感受。

首先從下面開始…

1. Android如何繪制UI

關于Android是如何去更新UI的,我相信有很多文章來介紹其中步驟以及過程,大體上可以用下圖來展示:

Android應用性能評測調優

從圖中可以看到,無論哪條路走下去始終都由SurfaceFlinger來控制最後更新。在Android版本更新過程中發現在Jelly Bean版本更新中,Google加入一個Project Butter來解決嚴重影響Android口碑問題之一的UI流暢性差的問題。而Project Butter中引入了三個核心元素,即VSync(垂直同步)、Triple Buffer和Choreographer。

2. 先VSync開始

在Android 4.1(Jelly Bean)中引入了VSync機制,是Vertical Synchronization(垂直同步)的縮寫,是一種在PC上已經很早就廣泛使用的技術,可以簡單地把它認為是一種定時中斷。(編者注:此處參考鄧凡平《Android Project Butter分析》一文)

Android應用性能評測調優

如上圖所示在VSync機制下的繪制過程。從上面的圖看CPU和GPU處理時間都很快都少于一個VSync的間隔也就是16ms,并且每個間隔都有繪制的情況下那麼目前的FPS即是60幀。當CPU和GPU處理時間都很慢或者因為其他的原因,比如在主線程中幹活太多那麼就會出現如下圖這樣的狀況。 

Android應用性能評測調優

從上圖可以看到CPU和GPU處理時間因為各種原因比較慢都大于一個VSync的間隔(16ms),那麼可以看到在第二個VSync還在處理A區域的繪制這樣就不可能實作理論上的FPS 60了同時也出現了丢幀(SF: Skipped Frame)。上圖為了便于了解用的是雙Buffer機制的情況,實際上Android 4.1在引入了Triple Buffer,是以當雙Buffer不夠用時Triple Buffer丢幀的情況如下圖所示。 

Android應用性能評測調優

Oh my ladygaga~~~這些把灑家看暈了…那打個比方講得通俗點。

VSync機制就像是一台轉速固定的發動機(60轉/s)。它每一轉帶動着去做一些UI相關的事情,但是不是每一轉都會有工作去做(就像有時在空擋,有時在D檔)。有時候因為各種阻力某一圈工作量比較重超過了16.6ms,那麼這台發動機這秒内就不是60轉了,當然也有可能被其他因素影響比如給油不足(主線程裡幹的活太多)等等。就會出現轉速降低的狀況我們把這個轉速叫做流暢度。
Android應用性能評測調優
Android應用性能評測調優

3. 從FPS&丢幀到流暢度(SM: SMoothness)

實際上在我們很多的Android App中,很少有需要不斷地去繪制的場景,很多時候都是靜态的。也就是會出現這樣的狀況,雖然1s中VSync的60個Loop中不是每個都在做繪制的工作FPS比較低,但并不能代表這個時候程式不流暢(如我将App放在那不動實測FPS為1)。是以FPS為1這個數并不能代表目前App在UI上界面不流暢,是以1s内VSync這個Loop運作了多少次更加能說明目前App的流暢程度。So…另2個名額比FPS更加能代表目前的App是否處于流暢的狀态同樣這2個名額更加能夠量化App卡頓的程度:

  • 丢幀(SF: Skipped Frame):如上圖所示情況應該在16ms完成工作卻因各種原因沒做完,占了下n個16ms的時間,相當于丢了n幀。
  • 流暢度(SM: SMoothness):和丢幀相對,在VSync機制中1s内Loop運作的次數。

1)和丢幀相對1s内有60個Loop因為某幾次工作時間超過了16ms(丢幀),這樣Loop就無法運作60次(理論最大值)。 

2)當流暢度越小的時候說明目前程式越卡頓。

4. 數數:如何得到流暢度(SM: SMoothness)

接着上面的結論如果在這樣的機制下每次Loop運作之前通知我下,我就記個數就好了。

很幸運我們在新的Android的那一套機制中找到了一個畫圖的打雜工Choreographer這個對象。根據Google的官方API文檔描述他是用來協調animations、input以及drawing時序的,并且每個Looper共用一個Choreographer對象。

Choreographer的定義和結構:

Android應用性能評測調優

5. 是以通過如上原理分析可以得出結論:

  • 根據了解文檔發現Android 4.1引入了VSync機制可以通過其Loop來了解目前App最高繪制能力。

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)。

  • 可以在Choreographer的回調FrameCallback中按秒計數表示目前App的流暢程度。

采用這樣方式就可以在App内部觀測目前App的流暢度。當然,還有更簡單的方法,采用GT工具擷取流暢度,見下面步驟說明。

6. 用GT動态注入被測程式擷取SM:

1)打開被測App,然後打開GT在插件中選擇GT Injector:

Android應用性能評測調優

2)選擇被測程序&點選射它:

Android應用性能評測調優

3)注入成功後Para界面會出現流暢度名額以及被插入程式的CPU占有率這些并且會帶上被插入的程序名。将流暢度後面小方框勾選(表明記錄SM值到log檔案),然後點選Gather & Warning下小紅圈(表明開始記錄數值)。

Android應用性能評測調優
Android應用性能評測調優

4)開始做相關的測試測試。

5)完成測試後在剛才的界面點選流暢度(SM)出現下列界面,然後點選磁盤圖示,儲存log到指定名字的檔案夾。

Android應用性能評測調優
Android應用性能評測調優

6)最後利用各種工具(比如應用寶)把log導入到PC端進行後期處理(檔案儲存在SD卡/GT/GW/程序名/自定義檔案夾名下)。 

Android應用性能評測調優
注:以上的操作因為涉及到程序注入需要手機Root權限,如果不能使用可以郵件給我,位址見文章末尾處。

7. 那麼SM實際的測試效果如何?

是以,我們拿a、b、c三個浏覽器為例,對比評測下這樣的資料和人感受是否對應得上。首先,我們為了把感官和人的感受對應上特把主動感官分數對應到以下幾種描述如下表:

Android應用性能評測調優

場景1. 浏覽妹子圖……看看流暢度(SM)和丢幀(SF)之間關系

來看看流暢度(SM)和丢幀(SF)之間關系…這個資料是用浏覽器浏覽妹子圖時采集。因為丢幀是個不連續的過程,是以後面的圖中丢幀都是以點來表示其離散的狀态。

Android應用性能評測調優

從上面圖可以看出:

  • 丢幀(SF)越多流暢度(SM)越低…
  • 26:16秒後到26:42之間流暢度很低并且丢幀最密集,在這段期間流暢度主觀評分在2.5。
  • 再看看這期間流暢度,丢幀和主觀的對應關系:
Android應用性能評測調優

從這個資料可以看到丢幀(SF)越多流暢度(SM)越低,并且主觀感覺是比較卡的(界面滑動明顯頓挫感,響應使用者輸入有種慢半拍的感覺)。

場景2. 看妹子圖……引入FPS看看這3者關系…

同樣這段看妹子的過程中主觀感受也是在2.5分:

Android應用性能評測調優

這個資料裡面引入了FPS資料。從上圖可以看出:

  • 雖然FPS曲線和SM曲線差不多而且同樣受丢幀的影響;
  • 裡面有幾段比較奇怪的地方:

1)流暢度很高FPS比較低,無丢幀情況…當時靜置在某個界面沒有動此時主觀評分應該在4.5左右; 

2)FPS比較高,丢幀很嚴重流暢度很低…當時在不斷重新整理很多圖檔出來主觀評分應該在2.0以下。

把這2部分資料放大看:

流暢度很高FPS比較低無丢幀:

Android應用性能評測調優

本場景資料統計: 

Android應用性能評測調優

這個局部場景雖然畫面一直在動,沒有丢幀FPS在20以下但是流暢度比較高。So…從次場景可以看出這樣流暢度SM比FPS更加适合來客觀描述Android App卡的程度。

8. 問題來了:這麼多資料實在hold不住

從上面可以看出資料量比較大而且幾個産品條曲線之間有交錯那如何評定哪個在某些場景下更好呢?于是我們就想:通過SM資料判斷App流暢情況,并給出一個定量的結果。

思路:

  1. 不能直接用平均值和方差。根據以往經驗,通過平均值、方差等一些名額,并不好說明問題。如果卡頓時間出現較短,測試時間較長,則平均值和方差這種名額不容易發現問題,但是又确實有卡頓。平均值和方差适合描述服從正态分布的随機變量,但是測試得到的SM值并不是這樣的随機變量。
  2. 将測試結果按卡頓和流暢分段,對每個卡頓區間段打分。參考了KM上一篇遊戲流暢度評分的文章,該文章結合FPS平均值和卡頓的程度以及頻率,對遊戲整體流暢度打分。但是普通App和遊戲差別還是比較大的。對普通App來說,使用者不是一直在操作,不同的操作差異也較大,是以卡頓的頻率一般較低,用平均值和卡頓的頻率打分得到的結果可能會偏高。是以把測試過程按照卡頓和流暢分段,計算每個卡頓區間的打分和持續時間可能更有參考意義。
  3. 總體打分時加大卡頓時的權重,降低流暢區間的權重。雖然我們重點關注的可能是卡頓的地方,但是競品測試,以及兩個版本對比又需要有總體評判結果,不能隻看局部。為了加大結果的區分度,對卡頓區間增權重重,對流暢區間降低權重。突出卡頓對整體評分的影響。是以,評估結果将包括兩部分:總體打分以及卡頓區間,流暢區間的持續時間和打分。 

流暢度評估方法:

1. 預處理,每5個(秒)一組,取最低值。如果5秒内出現多于一次卡頓(SM低于40),則再乘以一個和卡頓次數有關的權值(小于1)。說明:如果卡頓出現次數較少,平均值和方差不容易發現問題。是以沒有直接對資料評估,先進行了預處理,突出SM值低的部分,加大卡頓對總分的影響。

處理前三組資料:

Android應用性能評測調優

處理後三組資料: 

Android應用性能評測調優

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上測試):

測試方法:打開某網站,來回上下滑動,在滑動的過程中記錄流暢度資料。

Android應用性能評測調優

流暢度評估資料: 

Android應用性能評測調優
Android應用性能評測調優

從上面的資料可以看出滑動浏覽網頁的時候,其中c浏覽器略微好于其他兩個。當然這都是在性能比較好的手機(N4)上測試主觀感受差距不大但是從量化資料上可以看出優劣。評分差距就和主觀感受拉開分值差不多能對應上,從客觀上可以證明這套評分算法某種程度上的準确性。

轉至:http://www.csdn.net/article/2015-06-12/2824949