前言 在智能手機App競爭越來越激烈的今天,Android App各項性能如CPU、內(nèi)存消耗等都是我們在開發(fā)測試中需要關(guān)注的指標(biāo),如何將App打造得更加“優(yōu)雅”是我們需要不斷追求探索的方向,下面我們從內(nèi)存和流暢度兩個緯度來說說如何對Android App進行評測和調(diào)優(yōu)。 一、內(nèi)存 內(nèi)存不是無限使用的,如果內(nèi)存過大或泄漏會出現(xiàn)OOM(Out Of Memory)、UI不流暢等問題,因此內(nèi)存也是一個稀缺資源,我們應(yīng)該保證沒有內(nèi)存泄漏且對不需要使用的內(nèi)存及時釋放。一般內(nèi)存測試或分析內(nèi)存問題可以分為下面幾步:
1.內(nèi)存測試通用的方法 測試分析內(nèi)存有以下幾種方法:
Heap查看堆的分配情況:
主要關(guān)注兩項數(shù)據(jù): 1)Heap Size堆的大小,當(dāng)資源增加,當(dāng)前堆的空余空間不夠時,系統(tǒng)會增加堆的大小。 2)Allocated堆中已分配的大小,這是應(yīng)用程序?qū)嶋H占用的內(nèi)存大小,資源回收后,此項數(shù)據(jù)會變小。 注:如果進行反復(fù)操作,或堆的大小一直增加,則有內(nèi)存泄漏的隱患。 Allocation Tracker跟蹤內(nèi)存分配情況:
MAT(Memory Analyzer)
2. Android常見的內(nèi)存問題 Android常見的內(nèi)存問題有:
下面就是一個例子,static變量占用過大的內(nèi)存比例(7.1M),這里碰到該情況需要具體分析里面數(shù)據(jù)是否都是需要常駐的,不要把很多不相干的變量設(shè)為static屬性。
這里需要自己搜索代碼查看是哪里一直hold住了資源導(dǎo)致沒有釋放。
圖上可以看到Bitmap占用內(nèi)存很大(5.7M),利用MAT來找到他的outgoing和incoming引用: 可以找到這塊內(nèi)存的引用關(guān)系,然后找代碼。
在遇到圖片資源占用過大的情況,建議: 1)及時的銷毀;
Cursor用完記得關(guān)掉,如果實在不確定Cursor是否關(guān)閉,可以在onDestroy中關(guān)了。
總的來說,沒有嚴(yán)格意義上泄露只是你hold太久。 二、流暢度 對于App是否流暢這個維度,之前一直沒有一個客觀的數(shù)據(jù)來將用戶客觀感受和數(shù)據(jù)一一對應(yīng)起來。雖然之前有FPS(每秒幀數(shù))這個指標(biāo)來衡量,不過這對于App這樣的大部分時候可能沒有界面更新的軟件來說,是一個不恰當(dāng)?shù)目陀^數(shù)據(jù)(當(dāng)然FPS用于游戲或視頻類業(yè)務(wù)肯定是沒問題的)。在和我們的瀏覽器團隊溝通后,應(yīng)他們的需求(它不僅要做最快的瀏覽器,同時也要做最流暢的瀏覽器),MIG(專項測試組)多位同學(xué)一起來通過研究Android自身UI更新機制以及通過數(shù)學(xué)建模摸索出一個客觀數(shù)據(jù)指標(biāo)流暢度(SM: SMoothness)來量化流暢度這個客觀感受。 首先從下面開始…
關(guān)于Android是如何去更新UI的,我相信有很多文章來介紹其中步驟以及過程,大體上可以用下圖來展示:
從圖中可以看到,無論哪條路走下去始終都由SurfaceFlinger來控制最后更新。在Android版本更新過程中發(fā)現(xiàn)在Jelly Bean版本更新中,Google加入一個Project Butter來解決嚴(yán)重影響Android口碑問題之一的UI流暢性差的問題。而Project Butter中引入了三個核心元素,即VSync(垂直同步)、Triple Buffer和Choreographer。 2. 先VSync開始 在Android 4.1(JB)中引入了VSync機制,是Vertical Synchronization(垂直同步)的縮寫,是一種在PC上已經(jīng)很早就廣泛使用的技術(shù),可以簡單地把它認(rèn)為是一種定時中斷。
如上圖所示在VSync機制下的繪制過程。從上面的圖看CPU和GPU處理時間都很快都少于一個VSync的間隔也就是16ms,并且每個間隔都有繪制的情況下那么當(dāng)前的FPS即是60幀。當(dāng)CPU和GPU處理時間都很慢或者因為其他的原因,比如在主線程中干活太多那么就會出現(xiàn)如下圖這樣的狀況。
從上圖可以看到CPU和GPU處理時間因為各種原因比較慢都大于一個VSync的間隔(16ms),那么可以看到在第二個VSync還在處理A區(qū)域的繪制這樣就不可能實現(xiàn)理論上的FPS 60了同時也出現(xiàn)了丟幀(SF: Skipped Frame)。上圖為了便于理解用的是雙Buffer機制的情況,實際上Android 4.1在引入了Triple Buffer,所以當(dāng)雙Buffer不夠用時Triple Buffer丟幀的情況如下圖所示。
Oh my ladygaga~~~這些把灑家看暈了…那打個比方講得通俗點。 VSync機制就像是一臺轉(zhuǎn)速固定的發(fā)動機(60轉(zhuǎn)/s)。它每一轉(zhuǎn)帶動著去做一些UI相關(guān)的事情,但是不是每一轉(zhuǎn)都會有工作去做(就像有時在空擋,有時在D檔)。有時候因為各種阻力某一圈工作量比較重超過了16.6ms,那么這臺發(fā)動機這秒內(nèi)就不是60轉(zhuǎn)了,當(dāng)然也有可能被其他因素影響比如給油不足(主線程里干的活太多)等等。就會出現(xiàn)轉(zhuǎn)速降低的狀況我們把這個轉(zhuǎn)速叫做流暢度。
3. 從FPS&丟幀到流暢度(SM: SMoothness) 實際上在我們很多的Android App中,很少有需要不斷地去繪制的場景,很多時候都是靜態(tài)的。也就是會出現(xiàn)這樣的狀況,雖然1s中VSync的60個Loop中不是每個都在做繪制的工作FPS比較低,但并不能代表這個時候程序不流暢(如我將App放在那不動實測FPS為1)。所以FPS為1這個數(shù)并不能代表當(dāng)前App在UI上界面不流暢,因此1s內(nèi)VSync這個Loop運行了多少次更加能說明當(dāng)前App的流暢程度。So…另2個指標(biāo)比FPS更加能代表當(dāng)前的App是否處于流暢的狀態(tài)同樣這2個指標(biāo)更加能夠量化App卡頓的程度:
1)和丟幀相對1s內(nèi)有60個Loop因為某幾次工作時間超過了16ms(丟幀),這樣Loop就無法運行60次(理論最大值)。
4. 數(shù)數(shù):如何得到流暢度(SM: SMoothness) 接著上面的結(jié)論如果在這樣的機制下每次Loop運行之前通知我下,我就記個數(shù)就好了。 很幸運我們在新的Android的那一套機制中找到了一個畫圖的打雜工Choreographer這個對象。根據(jù)Google的官方API文檔描述他是用來協(xié)調(diào)animations、input以及drawing時序的,并且每個Looper共用一個Choreographer對象。 Choreographer的定義和結(jié)構(gòu):
5. 所以通過如上原理分析可以得出結(jié)論:
1) 固定每隔16.6ms執(zhí)行一次(這個值是一個靜態(tài)變量會根據(jù)系統(tǒng)版本不同而采不同的值,目前測試版本是16.6ms這樣最高的刷新的幀率就控制在60FPS以內(nèi));
采用這樣方式就可以在App內(nèi)部觀測當(dāng)前App的流暢度。當(dāng)然,還有更簡單的方法,采用GT工具獲取流暢度,見下面步驟說明。 6. 用GT動態(tài)注入被測程序獲取SM: 1)打開被測App,然后打開GT在插件中選擇GT Injector:
2)選擇被測進程&點擊射它: 3)注入成功后Para界面會出現(xiàn)流暢度指標(biāo)以及被插入程序的CPU占有率這些并且會帶上被插入的進程名。將流暢度后面小方框勾選(表明記錄SM值到log文件),然后點擊Gather & Warning下小紅圈(表明開始記錄數(shù)值)。
4)開始做相關(guān)的測試測試。 5)完成測試后在剛才的界面點擊流暢度(SM)出現(xiàn)下列界面,然后點擊磁盤圖標(biāo),保存log到指定名字的文件夾。
6)最后利用各種工具(比如應(yīng)用寶)把log導(dǎo)入到PC端進行后期處理(文件保存在SD卡/GT/GW/進程名/自定義文件夾名下)。 注:以上的操作因為涉及到進程注入需要手機Root權(quán)限,如果不能使用可以郵件給我,地址見文章末尾處。 7. 那么SM實際的測試效果如何? 所以,我們拿a、b、c三個瀏覽器為例,對比評測下這樣的數(shù)據(jù)和人感受是否對應(yīng)得上。首先,我們?yōu)榱税迅泄俸腿说母惺軐?yīng)上特把主動感官分?jǐn)?shù)對應(yīng)到以下幾種描述如下表:
場景1. 瀏覽妹子圖……看看流暢度(SM)和丟幀(SF)之間關(guān)系 來看看流暢度(SM)和丟幀(SF)之間關(guān)系…這個數(shù)據(jù)是用瀏覽器瀏覽妹子圖時采集。因為丟幀是個不連續(xù)的過程,所以后面的圖中丟幀都是以點來表示其離散的狀態(tài)。
從上面圖可以看出:
從這個數(shù)據(jù)可以看到丟幀(SF)越多流暢度(SM)越低,并且主觀感覺是比較卡的(界面滑動明顯頓挫感,響應(yīng)用戶輸入有種慢半拍的感覺)。 場景2. 看妹子圖……引入FPS看看這3者關(guān)系… 同樣這段看妹子的過程中主觀感受也是在2.5分: 這個數(shù)據(jù)里面引入了FPS數(shù)據(jù)。從上圖可以看出:
1)流暢度很高FPS比較低,無丟幀情況…當(dāng)時靜置在某個界面沒有動此時主觀評分應(yīng)該在4.5左右;
把這2部分?jǐn)?shù)據(jù)放大看: 流暢度很高FPS比較低無丟幀:
本場景數(shù)據(jù)統(tǒng)計:
這個局部場景雖然畫面一直在動,沒有丟幀F(xiàn)PS在20以下但是流暢度比較高。So…從次場景可以看出這樣流暢度SM比FPS更加適合來客觀描述Android App卡的程度。 8. 問題來了:這么多數(shù)據(jù)實在hold不住 從上面可以看出數(shù)據(jù)量比較大而且?guī)讉€產(chǎn)品條曲線之間有交錯那如何評定哪個在某些場景下更好呢?于是我們就想:通過SM數(shù)據(jù)判斷App流暢情況,并給出一個定量的結(jié)果。 思路:
流暢度評估方法:
處理前三組數(shù)據(jù):
處理后三組數(shù)據(jù):
2. 將處理后的數(shù)據(jù)按卡頓和流暢分段,針對每段打分。說明:如果只有最后總分,且流暢的時間較長,卡頓的數(shù)據(jù)容易被流暢的數(shù)據(jù)淹沒。而且有些測試場景存在一段流暢,一段卡頓的現(xiàn)象,卡頓并不一定在整個測試過程中存在。這樣分開流暢和卡頓的區(qū)間處 理,更容易看出卡頓的程度。 3. 根據(jù)測試經(jīng)驗,對SM值對應(yīng)的卡頓嚴(yán)重程度打分。說明:根據(jù)測試同學(xué)的經(jīng)驗,流暢度指標(biāo)SM低于40時,用戶能感知到卡頓,SM在20以下卡頓比較嚴(yán)重。因此在打分時,SM值在20以下時打分最低,對應(yīng)0-20,在20-30區(qū)間打分低,對應(yīng)20-60,30-40區(qū)間打 分較低,對應(yīng)60-70,40以上打分在70以上。 4. 總體打分時降低流暢區(qū)間的權(quán)重。說明:這樣處理的原因和第一項的原因一樣,我們更關(guān)注的是卡頓,流暢區(qū)間過長時會淹沒卡頓的數(shù)據(jù)。 然后我們拿同一個測試場景下的測試數(shù)據(jù)出來對比一下: 1)網(wǎng)頁滑動(Nexus 4上測試): 測試方法:打開某網(wǎng)站,來回上下滑動,在滑動的過程中記錄流暢度數(shù)據(jù)。 流暢度評估數(shù)據(jù): 從上面的數(shù)據(jù)可以看出滑動瀏覽網(wǎng)頁的時候,其中c瀏覽器略微好于其他兩個。當(dāng)然這都是在性能比較好的手機(N4)上測試主觀感受差距不大但是從量化數(shù)據(jù)上可以看出優(yōu)劣。評分差距就和主觀感受拉開分值差不多能對應(yīng)上,從客觀上可以證明這套評分算法某種程度上的準(zhǔn)確性。
本文為CSDN原創(chuàng),點擊“閱讀原文”可查看全文并參與討論。 如果您喜歡這篇文章,請點擊右上角“…”將本文分享給你的朋友。 |
|