流暢度測(cè)試簡(jiǎn)單的來(lái)說(shuō)就是Android頁(yè)面繪制。Android系統(tǒng)每秒60hz,也就是大約每16ms刷新一次界面。但是在我們使用APP過(guò)程中,經(jīng)常會(huì)看到頁(yè)面有卡頓,或者說(shuō)丟幀的現(xiàn)象。也就是說(shuō)可能此刻兩個(gè)頁(yè)面繪制的時(shí)間差超過(guò)0.1S(人眼視覺(jué)殘留0.1S)??偟膩?lái)說(shuō),就是頁(yè)面
原理分析
在確定衡量指標(biāo)之前,先來(lái)說(shuō)Android的UI更新機(jī)制。
在Android版本更新過(guò)程中,發(fā)現(xiàn)在Jelly Bean中Google加入了一個(gè)Project Butter,用來(lái)解決嚴(yán)重影響Android口碑的問(wèn)題之一“UI流暢性差”的問(wèn)題。而Project Butter中主要引入了三個(gè)核心元素:VSYNC(垂直同步)、Triple Buffer和Choreographer。
VSync是Vertical
Synchronization(垂直同步)的縮寫(xiě),是一種在PC上很早就廣泛使用的技術(shù),可以簡(jiǎn)單的把它認(rèn)為是一種定時(shí)中斷。而在Android 4.1(JB)中已經(jīng)開(kāi)始引入VSync機(jī)制。CPU和GPU的處理時(shí)間都少于一個(gè)VSync的間隔,即16.6ms。如果每個(gè)間隔都有繪制的情況下,當(dāng)前的FPS即為60幀。
VSync機(jī)制就像是播放動(dòng)畫(huà)片(60幀/s)。每次都會(huì)播放畫(huà)面,有的時(shí)候有人偷懶了,機(jī)器壞了,就會(huì)出現(xiàn)播放速度降低的狀況。我們把這個(gè)播放速度叫做流暢度。
從FPS&丟幀到流暢度
實(shí)際上在很多Android的App中,很少有需要不斷地去繪制的場(chǎng)景,很多時(shí)候頁(yè)面都是靜態(tài)的。也就是會(huì)出現(xiàn)這樣的狀況,雖然1s中VSync的60個(gè)Loop不是每個(gè)都在做繪制的工作,FPS會(huì)比較低,但并不代表這個(gè)時(shí)候程序不流暢(如我將App放著不動(dòng),實(shí)測(cè)FPS為1)。所以FPS較低并不能代表當(dāng)前App在UI上界面不流暢,而1s內(nèi)VSync這個(gè)Loop運(yùn)行了多少次更加能說(shuō)明當(dāng)前App的流暢程度。所以,下面這2個(gè)指標(biāo)比FPS更能代表當(dāng)前的App是否處于流暢的狀態(tài)。同樣這2個(gè)指標(biāo)更加能夠量化App卡頓的程度:
1)丟幀(SF: Skipped
Frame):如上圖2所示情況應(yīng)該在16.6ms完成工作卻因各種原因沒(méi)做完,占了后n個(gè)16.6ms的時(shí)間,相當(dāng)于丟了n幀。
2)流暢度(SM: SMoothness):和丟幀相對(duì),在VSync機(jī)制中1s內(nèi)Loop運(yùn)行的次數(shù)。
和丟幀相對(duì)1s內(nèi)有60個(gè)Loop因?yàn)槟硯状喂ぷ鲿r(shí)間超過(guò)了16.6ms(丟幀),這樣Loop就無(wú)法運(yùn)行60次(理論最大值)。
當(dāng)流暢度越小的時(shí)候說(shuō)明當(dāng)前程序越卡頓。
如何得到流暢度(SM: SMoothness)
接著上面的結(jié)論,如果在這樣的機(jī)制下每次Loop運(yùn)行之前進(jìn)行通知,記個(gè)數(shù)就好了。
很幸運(yùn)我們?cè)谛碌?/span>Android的那一套機(jī)制中找到了一個(gè)畫(huà)圖的打雜工Choreographer這個(gè)對(duì)象。根據(jù)Google的官方API文檔描述中,它是用來(lái)協(xié)調(diào)animations、input以及drawing時(shí)序的,并且每個(gè)Loop共用一個(gè)Choreographer對(duì)象。
結(jié)論
通過(guò)如上原理分析可以得出結(jié)論:
1) Android 4.1引入了VSync機(jī)制后,可以通過(guò)其Loop來(lái)了解當(dāng)前App最高繪制能力。
固定每隔16.6ms執(zhí)行一次(這個(gè)值是一個(gè)靜態(tài)變量,會(huì)根據(jù)系統(tǒng)版本不同而采用不同的值,目前測(cè)試版本是16.6ms這樣最高的刷新的幀率就控制在60FPS以內(nèi));
如果沒(méi)有以上事件的時(shí)候同樣也會(huì)運(yùn)行這樣一個(gè)Loop;
這個(gè)Loop在1s之內(nèi)運(yùn)行了多少次,即可以表示當(dāng)前App繪制的最高的能力,也就是Android App卡頓的程度;
另外,在一次Loop時(shí)如果執(zhí)行時(shí)間超過(guò)了16.6ms,那么用多于16.6ms的時(shí)間除以16.6ms,即是當(dāng)前App的丟幀(SF: Skipped Frame)。
2) 可以在Choreographer的回調(diào)FrameCallback中,按秒計(jì)數(shù)表示當(dāng)前App的流暢程度,即流暢度SM(SMoothness)。
采用這樣方式就可以在App內(nèi)部觀測(cè)當(dāng)前App的流暢度了。并且在丟幀的地方打印traceView,就可以知道丟幀的大概原因,大概位置。定位代碼問(wèn)題。
|
|
來(lái)自: Graf1p7uk0x6cl > 《待分類》