Android App性能評測分析-流暢度篇

1.前言

在手機(jī)App競爭越來越激烈的今天胸嘴,Android App的各項性能特別是流暢度不如IOS绪杏,安卓基于java虛擬機(jī)運(yùn)行轮锥,觸控響應(yīng)的延遲和卡頓比IOS系統(tǒng)嚴(yán)重得多勾扭。一些下拉上滑毡琉、雙指縮放快速打字等操作,安卓的流暢度都表現(xiàn)比較糟糕妙色,但是桅滋,對于App使用過程是否流暢,一直沒有一個可靠的指標(biāo)將用戶的客觀感受和數(shù)據(jù)一一對應(yīng)燎斩。雖然之前有FPS(每秒幀數(shù))作為游戲或視頻類App的性能指標(biāo)虱歪,但對于那些界面更新不多的App來說,仍不是一個合適的衡量數(shù)據(jù)栅表。以下會根據(jù)實(shí)際app性能測試案例笋鄙,展開進(jìn)行app性能評測之流暢度進(jìn)行原理分析和評測總結(jié)。

1.1流暢度相關(guān)概念了解

刷新率vs幀率

刷新率:每秒屏幕刷新次數(shù)怪瓶,手機(jī)屏幕的刷新率是60HZ
幀率:GPU在一秒內(nèi)繪制的幀數(shù)

撕裂vs掉幀

撕裂

因?yàn)槠聊坏乃⑿逻^程是自上而下萧落、自左向右的践美,如果幀率>刷新率,當(dāng)屏幕還沒有刷新n-1幀的數(shù)據(jù)時找岖,就開始生成第n幀的數(shù)據(jù)了陨倡,從上到下,覆蓋第n-1幀许布。如果此時刷新屏幕兴革,就會出現(xiàn)圖像的上半部分是第n幀的,下半部分是第n幀的現(xiàn)象蜜唾。CPU/GPU一直都在渲染杂曲。

丟幀

Android系統(tǒng)每隔16ms發(fā)出VSYNC信號,觸發(fā)GPU對UI進(jìn)行渲染袁余,如果你的某個操作花費(fèi)時間是24ms擎勘,系統(tǒng)在得到VSYNC信號的時候由于還沒有準(zhǔn)備好,就無法進(jìn)行更新任何內(nèi)容颖榜,那么用戶在32ms內(nèi)看到的會是同一幀畫面(卡頓現(xiàn)象)棚饵,即丟幀現(xiàn)象。

單緩存 vs VSYNC vs 雙緩存 vs 三緩存

  • 單緩存(沒有引入VSync )

    GPU向緩存中寫入數(shù)據(jù)掩完,屏幕從緩存中讀取數(shù)據(jù)噪漾,刷新后顯示。由于刷新率和幀率并不總是一致的藤为,很可能導(dǎo)致撕裂的現(xiàn)象怪与。為了解決單緩存的畫面撕裂問題,出現(xiàn)了雙緩存和 VSync 缅疟。

    單緩存.png
  • VSYNC 和 雙緩存

    雙緩存使用了兩個緩存區(qū): Back Buffer 分别、 Frame Buffer。當(dāng)寫入下一幀時存淫,GPU會先填充 Back Buffer 中耘斩,當(dāng)刷新屏幕時,屏幕從 Frame Buffer 中讀數(shù)據(jù)桅咆。VSYNC 主要是完成幀的復(fù)制括授,開始下一幀的渲染。

image.png

當(dāng)幀率大于刷新頻率時岩饼,通過使幀率被迫跟刷新頻率保持同步荚虚,從而避免畫面撕裂的現(xiàn)象(只有當(dāng) VSync 信號產(chǎn)生時仑鸥, CPU/GPU 才會開始繪制)次酌。當(dāng)VSync 信號產(chǎn)生時爵嗅,先完成Back Buffer 到 Frame Buffer的復(fù)制操作(通過交換內(nèi)存地址)兑巾,然后通知 CPU/GPU 繪制下一幀圖像。也只有VSync 信號發(fā)生時钞艇,才繪制下一幀梭稚。

image.png

當(dāng)刷新頻率>幀率時位隶,此時刷新屏幕,發(fā)出VSYNC 信號俭茧,由于CPU/GPU的渲染操作還沒有完成咆疗,就不把Back Buffer的數(shù)據(jù)復(fù)制到 Frame Buffer,此時就從Frame Buffer去取舊數(shù)據(jù)母债,這樣在兩個刷新周期里午磁,顯示的是同一幀數(shù)據(jù)。

  • 三重緩存
image.png

雙重緩存的缺陷在于:當(dāng) CPU/GPU 繪制一幀的時間超過 16 ms 時场斑,會產(chǎn)生 Jank漓踢。更要命的是,產(chǎn)生 Jank 的那一幀的顯示期間漏隐,GPU/CPU 都是在閑置的。
如下圖奴迅,A青责、B 和 C 都是 Buffer。
如果有第三個 Buffer 能讓 CPU/GPU 在這個時候繼續(xù)工作取具,那就完全可以避免第二個 Jank 的發(fā)生了脖隶!


image.png

1.2 VSync垂直同步

在Android版本更新過程中,發(fā)現(xiàn)在Jelly Bean中Google加入了一個Project Butter暇检,用來解決嚴(yán)重影響Android口碑的問題之一“UI流暢性差”的問題产阱。
而Project Butter中主要引入了三個核心元素:VSYNC(垂直同步)当船、Triple BufferChoreographer义屏。
VSync是VerticalSynchronization(垂直同步)的縮寫,是一種在PC上很早就廣泛使用的技術(shù)则酝,可以簡單的把它認(rèn)為是一種定時中斷悔据。而在Android 4.1(JB)中已經(jīng)開始引入VSync機(jī)制庄敛。CPU和GPU的處理時間都少于一個VSync的間隔,即16.6ms科汗。如果每個間隔都有繪制的情況下藻烤,當(dāng)前的FPS即為60幀。VSync機(jī)制就像是播放動畫片(60幀/s)头滔。每次都會播放畫面怖亭,有的時候有人偷懶了,機(jī)器壞了坤检,就會出現(xiàn)播放速度降低的狀況兴猩。我們把這個播放速度叫做流暢度。

Drawing without VSync.png

Drawing with VSync.png

VSync機(jī)制.png

1.3 理解FPS原理

FPS即Frames per second缀蹄,>>點(diǎn)擊這篇文章峭跳,解釋的非常清楚膘婶。
用過flash的人應(yīng)該知道動畫片其實(shí)是由一張張畫出來的圖片連貫執(zhí)行產(chǎn)生的效果,當(dāng)一張張獨(dú)立的圖片切換速度足夠快的時候蛀醉,會欺騙我們的眼睛悬襟,以為這是連續(xù)的動作。反之類推拯刁,當(dāng)你的圖片切換不夠快的時候脊岳,就會被人眼看穿,反饋給用戶的就是所謂的卡頓現(xiàn)象垛玻。
想要讓大腦覺得動作是連續(xù)的割捅,至少是每秒10-12幀的速度,而想達(dá)到流暢的效果帚桩,至少需要每秒24幀亿驾。這也是為什么電影片源通常都是24幀的原因,好奇的同學(xué)點(diǎn)擊
>>知乎高知
看看大神的解答账嚎。不過60幀每秒的流暢度是最佳的莫瞬,我們的目標(biāo)就是讓程序的流暢度能接近60幀每秒,當(dāng)然超過60幀速的話大部分人還是會受不了的郭蕉。

系統(tǒng)獲取FPS的原理是:1s 內(nèi) SurfaceFLinger 提交到屏幕的幀數(shù)疼邀。
計算公式:1000ms / 60 frames ≈ 16.67 ms/frames

原來的測試產(chǎn)品的流暢度,F(xiàn)PS是一個重要的指標(biāo)召锈,但是用了一段時間后旁振,人們就發(fā)現(xiàn)了這樣兩個問題

Question:
1)為什么有時候FPS很低,但是我們卻不覺得App卡頓涨岁?
2)App停止操作之后拐袜,F(xiàn)PS還是一直在變化,這樣的情況是否會影響FPS的準(zhǔn)確度卵惦?

后來測試人員分析了系統(tǒng)獲取FPS的原理后阻肿,找到了那兩個問題的答案:

Answer:
1)有時候FPS很低,我們卻感覺不到卡頓沮尿,因?yàn)楸緛砭陀貌坏侥敲锤叩腇PS丛塌,比如畫一個動畫只畫了0.5秒就畫完了,那么FPS最高也只有30幀/秒(標(biāo)準(zhǔn)是60幀/每秒)畜疾,但這并不代表它是卡頓的赴邻,用0.5秒動畫就畫完了,不能為了湊夠60幀/秒啡捶,在做個1s的動畫吧姥敛。而如果屏幕根本沒有繪制需求,即屏幕顯示的畫面是靜止的瞎暑,那FPS就為0彤敛。
2)App停止操作后FPS還一直變化与帆,是因?yàn)槠聊幻恳粠暮铣啥际轻槍κ謾C(jī)里的所有進(jìn)程,那么即使你的App停止了繪制墨榄,手機(jī)里其他進(jìn)程可能還在繪制玄糟,比如通知欄的各種消息,這會導(dǎo)致FPS繼續(xù)變化袄秩。

2. 如何計算流暢度

從上一節(jié)的原理分析來看阵翎,對流暢度的評價沒有一個既定的測量標(biāo)準(zhǔn)。不同的應(yīng)用有相對適應(yīng)的計算方式之剧,總結(jié)如下:

系統(tǒng)合成幀率(FPS):數(shù)據(jù)形式最為直觀(FPS 是最早的顯示性能指標(biāo)郭卫,而且在多個平臺中都有著類似的定義),且對系統(tǒng)平臺的要求最低(API level 1)背稼,游戲贰军、視頻等連續(xù)繪制的應(yīng)用可以考慮選用,但不適用于絕大多數(shù)非連續(xù)繪制的應(yīng)用蟹肘;
流暢度(SM):數(shù)據(jù)形式與 FPS 類似谓形,可以很好的彌補(bǔ) FPS 無法準(zhǔn)確刻畫非連續(xù)繪制的應(yīng)用顯示性能的缺陷;
應(yīng)用跳幀次數(shù)疆前、幅度(Aggregate frame stats):除了對系統(tǒng)平臺有較高的要求以外,其采集方式最為簡單(系統(tǒng)自帶功能)聘萨;
丟幀(Skipped frames):與 Aggregate frame stats 類似竹椒, 信息量相對較少,但可適用范圍更廣

2.1 FPS獲取

APP需要盡可能的超過24幀/秒米辐,接近60幀/秒的速度胸完,并且在使用的過程中保持這個速率,因此這意味著我們的程序需要在16.67ms內(nèi)處理一幅畫面內(nèi)的所有事翘贮,并保持住這個狀態(tài)赊窥。
計算公式:1000ms / 60 frames ≈ 16.67 ms/frames

2.1.1 GPU呈現(xiàn)模式分析

操作方法:通過 [設(shè)置]->[開發(fā)者選項]->[GPU呈現(xiàn)模式分析] ->[在屏幕上顯示為條形圖] 進(jìn)行直觀的取樣,截圖如下:

GPU條形圖.png

解讀:屏幕下方的柱形圖會持續(xù)刷新狸页,最上方會有一根綠色的線锨能,代表的是16ms的閾值,超過這個界限表示當(dāng)前幀繪制的時間出現(xiàn)了延遲芍耘,及卡頓現(xiàn)象址遇,后面會詳細(xì)介紹原因。橫坐標(biāo)表示時間的持續(xù)斋竞,每一根柱形圖表示當(dāng)前幀的繪制時間倔约。因此我們在使用的過程中,下面的柱形圖會一直的刷新坝初,單位是ms浸剩。各位看官是否有注意到每一幀的柱形圖顏色不一樣呢(注:不同手機(jī)的顏色不一樣钾军,僅限安卓4.0以上版本參考)
優(yōu)點(diǎn):可直接在手機(jī)上操作,方便直觀
缺點(diǎn):這個方式獲取到的渲染時間只是UI主線程上的繪制行為绢要±艄В“GPU呈現(xiàn)模式分析”的數(shù)據(jù)只能說明個現(xiàn)象,比如上面提到的數(shù)據(jù)袖扛,能說明在實(shí)際運(yùn)行中會有短暫的長時間繪制問題砸泛。但造成問題的具體原因并沒有說明。
而且“GPU呈現(xiàn)模式分析”顯示的是最后128幀的數(shù)據(jù)蛆封,但丟幀也有可能是兩幀之間存在長時間的操作而造成的唇礁。
GPU渲染卡頓.png

2.1.2 通過gfxinfo獲取

操作:設(shè)備連接usb數(shù)據(jù)線,使用adb調(diào)試工具惨篱,隨后對返回的數(shù)據(jù)進(jìn)行適當(dāng)處理便可以得到此時此刻app的fps盏筐。
adb shell dumpsys gfxinfo yourpackagename
解讀
Draw:是消耗在構(gòu)建java顯示列表DisplayList的時間砸讳。說白了就是執(zhí)行每一個View的onDraw方法,創(chuàng)建或者更新每一個View的DisplayList對象的時間琢融。
Process:表示是消耗在Android的2D渲染器執(zhí)行顯示列表的時間,view越多簿寂,要執(zhí)行的繪圖命令就越多漾抬,時間就越長
Execute:消耗在排列每個發(fā)送過來的幀的順序的時間.或者說是CPU告訴GPU渲染一幀的時間,這是一個阻塞調(diào)用,因?yàn)镃PU會一直等待GPU發(fā)出接到命令的回復(fù)。所以這個時間常遂,一般都很短纳令。

Draw + Prepare+Process + Execute = 完整顯示一幀 ,這個時間要小于16ms才能保存每秒60幀克胳。

將數(shù)據(jù)復(fù)制到excel中平绩,然后將數(shù)據(jù)生成“堆積柱形圖”如下:

image.png

image.png

缺點(diǎn): 這種方式是最普遍也是最常用的一種,但在使用上有明顯的痛點(diǎn)漠另,一是設(shè)備需要連接usb捏雌,二是必須是Android M 版本以上才支持,三是adb命令返回的數(shù)據(jù)并不是實(shí)時fps笆搓,需要經(jīng)過處理才能得到性湿,因此不能在測試app的過程中實(shí)時顯示fps

2.1.3 通過系統(tǒng)層級SurfaceFlinger獲取

原理:在 Android 系統(tǒng)中,SurfaceFlinger 扮演了系統(tǒng)中所有 Surface 的管理者的角色砚作,當(dāng)應(yīng)用程序所對應(yīng)的 Surface 更新之后窘奏,絕大多數(shù)的 Surface 都將在 SurfaceFlinger 之中完成了合并的工作之后,最終才會在 Screen 上顯示出來葫录。
知道android繪制原理的人應(yīng)該能明白着裹,SurfaceFlinger就是負(fù)責(zé)繪制Android應(yīng)用程序UI的服務(wù),所以surfaceFlinger能反應(yīng)出整體繪制情況,一般正常情況都是連續(xù)的骇扇,如果出現(xiàn)空檔摔竿,一種是沒有操作或者滑動到頭,沒東西需要繪制少孝,這種屬于正常继低,另一種就是有問題存在,有其他操作時間過長稍走。

操作:設(shè)備連接usb數(shù)據(jù)線袁翁,使用adb調(diào)試工具,
adb shell dumpsys SurfaceFlinger packagename

2.2 Aggregate frame stats指標(biāo)的計算方法

首先需要說明的是 Aggregate frame stats 不是一個指標(biāo)婿脸,而是一系列指標(biāo)集合粱胜。我們來看一個具體的 Aggregate frame stats 的例子:

Stats since: 752958278148ns

Total frames rendered: 82189

Janky frames: 35335 (42.99%)

90th percentile: 34ms

95th percentile: 42ms

99th percentile: 69ms

Number Missed Vsync: 4706

Number High input latency: 142

Number Slow UI thread: 17270

Number Slow bitmap uploads: 1542

Number Slow draw: 23342

以上統(tǒng)計信息的實(shí)現(xiàn)可以詳見源碼:GfxMonitorImpl.java

在 Android M 以上的系統(tǒng)上,上述信息的獲取十分方便(事實(shí)上也只有這些系統(tǒng)能夠獲取這些信息)狐树。僅需要執(zhí)行以下命令即可:

adb shell dumpsys gfxinfo <PACKAGE_NAME>

優(yōu)點(diǎn):除了對系統(tǒng)平臺有較高的要求以外焙压,其采集方式最為簡單(系統(tǒng)自帶功能);

2.3 丟幀計算

在一次Loop時如果執(zhí)行時間超過了16.6ms抑钟,那么用多于16.6ms的時間除以16.6ms涯曲,即是當(dāng)前App的丟幀(SF: Skipped Frame)
在16.6ms完成工作卻因各種原因沒做完,占了后n個16.6ms的時間在塔,相當(dāng)于丟了n幀
故:

SF=處理幀數(shù) / (處理幀數(shù) + 額外的垂直同步脈沖) * 60 計算(其中處理幀數(shù)常為128)
這個指標(biāo)的就是指當(dāng)前應(yīng)用在丟幀發(fā)生時的丟幀幀數(shù)幻件。

針對 Logcat 方案, 該數(shù)值直接在 Logcat 中輸出蛔溃,并且?guī)в袝r間信息傲武。

04-18 16:31:24.957 I/Choreographer(24164): Skipped 4 frames!  The application may be doing too much work on its main thread.
04-18 16:31:25.009 I/Choreographer(24164): Skipped 2 frames!  The application may be doing too much work on its main thread.

針對 Choreographer.FrameCallback 方案 以及 代碼注入方案,我們可能很方便的通過計算前后兩幀開始渲染的時間差獲得這一數(shù)值城榛,同樣方便。同樣與 Logcat 方案 不同的是态兴,它也是可以設(shè)計成實(shí)時計算的狠持。
缺點(diǎn):Android4.2+系統(tǒng),適用于SW/HW Rendering 及 部分 OpenGL Rendering

2.4 流暢度計算

原理:VSync 機(jī)制就像一臺轉(zhuǎn)速固定的發(fā)動機(jī)(60轉(zhuǎn)/s)瞻润,每一轉(zhuǎn)帶動著做一些 UI 相關(guān)的事情喘垂。有時候因?yàn)楦鞣N阻力, 某一圈的工作量比較重绍撞, 超過了 16.6ms, 那么這一秒內(nèi)就不是 60 轉(zhuǎn)了正勒。
我們通過測量這個轉(zhuǎn)速,來評判應(yīng)用的流暢度傻铣。
和丟幀相對章贞,在VSync機(jī)制中1s內(nèi)Loop運(yùn)行的次數(shù)。和丟幀相對1s內(nèi)有60個Loop因?yàn)槟硯状喂ぷ鲿r間超過了16.6ms(丟幀)非洲,這樣Loop就無法運(yùn)行60次(理論最大值)鸭限。當(dāng)流暢度越小的時候說明當(dāng)前程序越卡頓蜕径。

計算方式:SM = 幀率(60) * (單位時長總幀數(shù) - 單位時長丟幀數(shù)) / 單位時長總幀數(shù)

操作:
VSync機(jī)制客戶通過其Loop來了解當(dāng)前App最高繪制能力,其機(jī)制如下:

1)固定每隔16.6ms執(zhí)行一次败京;

2)如果沒有繪制事件的時候也會運(yùn)行這樣一個Loop兜喻;

3)Loop在1s之內(nèi)運(yùn)行了多少次,即可以表示當(dāng)前App繪制的最高能力赡麦,也就是App卡頓的程度朴皆。

if(存在幀的繪制):

      Loop = 1 幀繪制完成所占用的Vsync間隔

else:

      Loop = 1個Vsync間隔

所以SM計算方法為Loop在1s內(nèi)運(yùn)行了多少次(Loops per seconds),那么我們可以直接在App代碼中通過Choreographer的回調(diào)FrameCallback來計算Loop被運(yùn)行了幾次泛粹,從而知道應(yīng)用的流暢度遂铡。但在實(shí)際情況下我們不一定能修改代碼(實(shí)際發(fā)布的版本不允許加入測試代碼)或者根本拿不到代碼(譬如和競品進(jìn)行對比)。

所以介紹一種更簡單直觀測量Android應(yīng)用流暢度的方法戚扳,就是通過開源測試工具GT(http://gt.qq.com)忧便。

優(yōu)點(diǎn):數(shù)據(jù)形式與 FPS 類似,可以很好的彌補(bǔ) FPS 無法準(zhǔn)確刻畫非連續(xù)繪制的應(yīng)用顯示性能的缺陷帽借;
缺點(diǎn):Android4.2+系統(tǒng)珠增,適用于SW/HW Rendering 及 部分 OpenGL Rendering

3.卡頓問題分析工具

分析UI卡頓我們一般都借助工具,通過工具一般都可以直觀的分析出問題原因砍艾,從而反推尋求優(yōu)化方案蒂教,具體如下細(xì)說各種強(qiáng)大的工具

3.1 Hierarchy Viewer使用

我們可以通過SDK提供的工具HierarchyViewer來進(jìn)行UI布局復(fù)雜程度及冗余等分析

通過命令啟動HierarchyViewer

Hierarchyviewer

接下來Hierarchy window窗口打開:

Hierarchy.png

一個Activity的View樹,通過這個樹可以分析出View嵌套的冗余層級脆荷,以及每個View在繪制的使用時長也有表示凝垛。

3.2 使用Lint進(jìn)行資源及冗余UI布局等優(yōu)化

冗余資源及邏輯等也可能會導(dǎo)致加載和執(zhí)行緩慢,這可以使用Link工具蜓谋,發(fā)現(xiàn)代碼中的流暢度性能問題梦皮;

在AndroidStudio 1.4版本中使用Lint最簡單的辦法:就是將鼠標(biāo)放在代碼區(qū)點(diǎn)擊右鍵->Analyze->Inspect Code–>界面選擇你要檢測的模塊->點(diǎn)擊確認(rèn)開始檢測,等待一下后會發(fā)現(xiàn)如下結(jié)果:


image.png

如果存在冗余的UI層級嵌套桃焕,會進(jìn)行高亮顯示剑肯, 我們根據(jù)提示可以點(diǎn)擊跳進(jìn)去進(jìn)行優(yōu)化處理掉的。

3.3 DDMS內(nèi)存查看器

由于Android系統(tǒng)會依據(jù)內(nèi)存中不同的內(nèi)存數(shù)據(jù)類型分別執(zhí)行不同的GC操作观堂,常見應(yīng)用開發(fā)中導(dǎo)致GC頻繁執(zhí)行的原因主要可能是因?yàn)槎虝r間內(nèi)有大量頻繁的對象創(chuàng)建與釋放操作让网,也就是俗稱的內(nèi)存抖動現(xiàn)象,或者短時間內(nèi)已經(jīng)存在大量內(nèi)存暫用介于閾值邊緣师痕,接著每當(dāng)有新對象創(chuàng)建時都會導(dǎo)致超越閾值觸發(fā)GC操作


memory monitor.png

根據(jù)內(nèi)存抖動現(xiàn)象溃睹,查看log日志進(jìn)行分析:

image.png

如果看到,這種不停的大面積打印GC導(dǎo)致所有線程暫停的操作必定會導(dǎo)致UI視覺的卡頓胰坟,所以我們要避免此類問題的出現(xiàn)因篇,具體的常見優(yōu)化方式如下:

  1. 檢查代碼,盡量避免有些頻繁觸發(fā)的邏輯方法中存在大量對象分配;

  2. 盡量避免在多次for循環(huán)中頻繁分配對象惜犀;

  3. 避免在自定義View的onDraw()方法中執(zhí)行復(fù)雜的操作及創(chuàng)建對象(譬如Paint的實(shí)例化操作不要寫在onDraw()方法中等)铛碑;

  4. 對于并發(fā)下載等類似邏輯的實(shí)現(xiàn)盡量避免多次創(chuàng)建線程對象,而是交給線程池處理虽界。

有了上面說明GC導(dǎo)致的性能后我們就該定位分析問題了汽烦,我們可以通過運(yùn)行DDMS->Allocation Tracker標(biāo)簽打開一個新窗口,然后點(diǎn)擊Start Tracing按鈕莉御,接著運(yùn)行你想分析的代碼撇吞,運(yùn)行完畢后點(diǎn)擊GetAllocations按鈕就能夠看見一個已分配對象的列表,如下:


image.png

3.4 Tracer for OpenGL ES

可以記錄和分析APP每一幀的繪制過程礁叔,以及列出所有乃至的OpenGL ES 的繪制函數(shù)和耗時牍颈;該工具操作后會生成一份記錄App繪制過程和gltrace文件。

3.5 BlockCanary分析android卡頓

在復(fù)雜的項目環(huán)境中琅关,由于歷史代碼龐大煮岁,業(yè)務(wù)復(fù)雜,包含各種第三方庫涣易,所以在出現(xiàn)了卡頓的時候画机,我們很難定位到底是哪里出現(xiàn)了問題,即便知道是哪一個Activity/Fragment新症,也仍然需要進(jìn)去里面一行一行看步氏,動輒數(shù)千行的類再加上跳來跳去調(diào)來調(diào)去的,結(jié)果就是不了了之隨它去了徒爹,實(shí)在不行了再優(yōu)化吧荚醒。于是一拖再拖,最后可能壓根就改不動了隆嗅,客戶端越來越卡界阁。

Android應(yīng)用卡頓是非常普遍的現(xiàn)象,偶爾出現(xiàn)ANR胖喳。只有當(dāng)APP出現(xiàn)ANR铺董,我們才能得到當(dāng)前堆棧信息。當(dāng)應(yīng)用只是卡頓或只是不太流暢的時候禀晓,我們能不能找出卡頓元兇呢?不依賴Debug和源碼的情況坝锰,能不能找出卡頓的堆棧信息呢粹懒?我們需要找到一種方法來檢測哪些函數(shù)可能會使應(yīng)用發(fā)生ANR,在開發(fā)階段就能找出卡頓元兇顷级,提高應(yīng)用流暢度凫乖。

BlockCanary就是來解決這個問題的。告別打點(diǎn),告別Debug帽芽,哪里卡頓删掀,一目了然,讓優(yōu)化代碼變得有的放矢导街。
具體使用方法請點(diǎn)擊:

BlockCanary介紹 地址
BlockCanary — 輕松找出Android App界面卡頓元兇

4.XX銀行-性能評測對比掉幀率案例

4.1 總覽

此次質(zhì)量開放平臺-評測中心(http://fit-stg1.jryzt.com/Hyperion-server/html/index.html)的性能測試的流暢度測試主要是針對場景頁面的掉幀率數(shù)據(jù)采集進(jìn)行對比分析披泪, 原理公式為:掉幀率=處理幀數(shù) / (處理幀數(shù) + 額外的垂直同步脈沖) * 60 計算(其中處理幀數(shù)常為128)。一般掉幀率超過10%搬瑰,我們就認(rèn)為存在卡頓有必要進(jìn)行分析定位款票。

4.2 掉幀率對比分析案例

這里選取了同一家銀行的兩個APP與行業(yè)競品進(jìn)行掉幀率對比分析,從掉幀率對比看泽论,行業(yè)競品均值為4.1%艾少,90分位約13.1%,75分位約27.5%翼悴,中位數(shù)約39.6%缚够,25分位約59.9%。


掉幀率對比.png

【福建農(nóng)信】掉幀率為1.783%鹦赎,表現(xiàn)良好谍椅,打敗了行業(yè)90%以上的競品
【榕商Bank】掉幀率為6.244%,表現(xiàn)良好钙姊,打敗了行業(yè)90%以上的競品

整體得分對比分析:
從首頁啟動到加載完成場景分析毯辅,【福建農(nóng)信】實(shí)際啟動到首頁場景只有一個簡單的未登錄頁,相比于豐富多樣的【榕商Bank】來說屬于非常簡單的頁面煞额,但是它的掉幀率與豐富資源的【榕商Bank】比較相差不遠(yuǎn)思恐。

【福建農(nóng)信】首頁掉幀率問題分析:
單純從頁面表象觀察,【福建農(nóng)信】啟動時膊毁,未登錄頁是從APP背景頁下方飄進(jìn)漸漸上升在頁面中間胀莹,然后抖動一下再靜止,有一種PPT飛入的動態(tài)效果婚温。
通過深入分析得出【福建農(nóng)信】應(yīng)用交互中主線程存在卡頓描焰,存在 Activity(LoginActivity)切換過慢的現(xiàn)象:


image.png

cn.com.fjnx.mobilebank.per.activity.account.LoginActivity.onCreate(阻塞1639 ms)
com.yitong.fjnx.mbank.android.Splash.onCreate(阻塞1717 ms)
建議【福建農(nóng)信】優(yōu)化啟動時未登錄頁進(jìn)入的方式

【榕商Bank】首頁掉幀率問題分析:
首頁加載掉幀率為8.2%,通過GPU過度繪制調(diào)試發(fā)現(xiàn):com.pingan.fstandard.activity.MainActivity存在過度繪制栅螟。實(shí)際上是因?yàn)檫\(yùn)營Banner位有輪播動態(tài)效果荆秦,輪播間隔時間設(shè)置的比較長力图,導(dǎo)致評測時掉幀率偏高,但是這是合理的產(chǎn)品設(shè)計吃媒,而且也不影響用戶體驗(yàn)吕喘。

綜上對比,【榕商Bank】流暢度表現(xiàn)優(yōu)于【福建農(nóng)信】氯质,【福建農(nóng)信】掉幀率仍然有優(yōu)化空間。

5.App端卡頓問題排查思路

1)UI線程卡頓

問題:UI線程中有I/O讀寫闻察、數(shù)據(jù)庫訪問等耗時操作,導(dǎo)致UI線程卡頓;
定位及解決:TraceView 尋找卡住主線程的地方蜓陌,Systrace 獲取 app 運(yùn)行是線程的信息以及 API 的執(zhí)行情況,避免在主線程執(zhí)行 IO 操作吩蔑。

2) 復(fù)雜钮热、不合理的布局或過度繪制

問題:不合理的布局雖然可以完成功能,但隨著控件數(shù)量越多烛芬、布局嵌套層次越深隧期,展開布局花費(fèi)的時間幾乎是線性增長,性能也就越差赘娄;
定位及解決: 避免OverDraw導(dǎo)致的性能損耗仆潮;可以參考《Android性能優(yōu)化(二)之布局優(yōu)化面面觀》

3)同一時間動畫執(zhí)行的次數(shù)過多

問題:同一時間動畫執(zhí)行的次數(shù)過多,導(dǎo)致CPU或GPU負(fù)載過重遣臼;

4) 內(nèi)存使用異常導(dǎo)致卡頓

問題:內(nèi)存抖動性置、內(nèi)存泄漏都會導(dǎo)致:GC的次數(shù)越多、消耗在GC上的時間越長揍堰,CPU花在界面繪制上的時間相應(yīng)越短鹏浅;
解決:節(jié)省內(nèi)存的分配空間,盡可能的降低GC的頻率屏歹,縮短GC的平均時間隐砸;CPU不被占用,卡頓的幾率就會更低蝙眶; 可以參考《Android性能優(yōu)化(四)之內(nèi)存優(yōu)化實(shí)戰(zhàn)》

5) 冗余資源及邏輯等導(dǎo)致加載和執(zhí)行緩慢季希;

問題:對線程開啟方式的不同選擇以及不同配置都可能導(dǎo)致卡頓的發(fā)生;

解決:任何耗時操作正確的移到異步里幽纷,類如I/O讀寫式塌、數(shù)據(jù)庫訪問等都應(yīng)該采用異步的方式,不能有“只是一個很小的文件”之類的想法友浸,防微杜漸峰尝;

參考:
Android 性能模式 第一季
Android性能優(yōu)化典范 - 第1季
Android性能優(yōu)化之渲染篇
Android性能優(yōu)化系列——Profile GPU Rendering
Profile GPU Rendering Walkthrough
Android 顯示原理簡介
Android 4.4 Graphic系統(tǒng)詳解(2) VSYNC的生成
理解 VSync
了解Android 4.1,之三:黃油項目 —— 運(yùn)作機(jī)理及新鮮玩意
Hierarchy Viewer使用詳解

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末尾菇,一起剝皮案震驚了整個濱河市境析,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌派诬,老刑警劉巖劳淆,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異缆八,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)栏妖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進(jìn)店門吊趾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來论泛,“玉大人蛹屿,你說我怎么就攤上這事》仄埃” “怎么了载绿?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵崭庸,是天一觀的道長怕享。 經(jīng)常有香客問我镰踏,道長奠伪,這世上最難降的妖魔是什么首懈? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任究履,我火速辦了婚禮最仑,結(jié)果婚禮上泥彤,老公的妹妹穿的比我還像新娘吟吝。我一直安慰自己牵囤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布炕贵。 她就那樣靜靜地躺著称开,像睡著了一般鳖轰。 火紅的嫁衣襯著肌膚如雪蕴侣。 梳的紋絲不亂的頭發(fā)上臭觉,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天蝠筑,我揣著相機(jī)與錄音什乙,去河邊找鬼。 笑死辅愿,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鸽素。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼燕差,長吁一口氣:“原來是場噩夢啊……” “哼坝冕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起测暗,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤碗啄,失蹤者是張志新(化名)和其女友劉穎稚字,沒想到半個月后厦酬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仗阅,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡减噪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年旋廷,在試婚紗的時候發(fā)現(xiàn)自己被綠了饶碘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碍岔。...
    茶點(diǎn)故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡闲孤,死狀恐怖洞拨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情歹河,我是刑警寧澤秸歧,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布键菱,位于F島的核電站今布,受9級特大地震影響部默,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蘑志,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一急但、第九天 我趴在偏房一處隱蔽的房頂上張望波桩。 院中可真熱鬧请敦,春花似錦、人聲如沸萤皂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至凡桥,卻和暖如春缅刽,著一層夾襖步出監(jiān)牢的瞬間蠢络,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留芦疏,地道東北人酸茴。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓薪捍,卻偏偏與公主長得像配喳,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子被济,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內(nèi)容