Android丟幀分析與優(yōu)化

如果你覺得應(yīng)用卡頓、不夠流暢蛤铜,不用懷疑,很大原因是沒有在16ms完成你的工作。

著名的“16ms”原則:
我們通常都會(huì)提到60fps(Frame Per Second)與16ms埋涧,可是知道為何會(huì)是以程序是否達(dá)到60fps來作為App性能的衡量標(biāo)準(zhǔn)嗎?
60fps:人眼與大腦之間的協(xié)作無法感知超過60fps的畫面更新奇瘦。
*16ms:因?yàn)锳ndroid設(shè)定的刷新率是60fps棘催,也就是每秒60幀,即16ms=1000/60Hz
Android系統(tǒng)每隔16ms會(huì)發(fā)出VSYNC信號(hào)重繪我們的界面耳标。

就像這樣:

如果你的某個(gè)操作花費(fèi)時(shí)間是24ms醇坝,系統(tǒng)在得到VSYNC信號(hào)的時(shí)候就無法進(jìn)行正常渲染,這樣就發(fā)生了丟幀現(xiàn)象次坡。那么用戶在32ms內(nèi)看到的會(huì)是同一幀畫面呼猪。

關(guān)于VSYNC

為了理解App是如何進(jìn)行渲染的,我們必須了解手機(jī)硬件是如何工作砸琅,那么就必須理解什么是VSYNC宋距。
在講解VSYNC之前,我們需要了解兩個(gè)相關(guān)的概念:

Refresh Rate:代表了屏幕在一秒內(nèi)刷新屏幕的次數(shù)明棍,這取決于硬件的固定參數(shù)乡革,例如60Hz。
Frame Rate:代表了GPU在一秒內(nèi)繪制操作的幀數(shù)摊腋,例如30fps沸版,60fps。

GPU會(huì)獲取圖形數(shù)據(jù)進(jìn)行渲染兴蒸,然后硬件負(fù)責(zé)把渲染后的內(nèi)容呈現(xiàn)到屏幕上视粮,他們兩者不停的進(jìn)行協(xié)作。


不幸的是橙凳,刷新頻率和幀率并不是總能夠保持相同的節(jié)奏蕾殴。如果發(fā)生幀率與刷新頻率不一致的情況笑撞,就會(huì)容易出現(xiàn)Tearing的現(xiàn)象(畫面上下兩部分顯示內(nèi)容發(fā)生斷裂,來自不同的兩幀數(shù)據(jù)發(fā)生重疊)钓觉。


雙緩沖機(jī)制

其實(shí)上面說的就是Android的雙緩沖機(jī)制茴肥,而雙緩沖技術(shù)一直貫穿這個(gè)Android系統(tǒng)。因?yàn)閷?shí)際上幀的數(shù)據(jù)就是保存在兩個(gè)緩沖區(qū)中荡灾,A緩沖用來顯示當(dāng)前幀瓤狐,那么B緩沖就用來緩存下一幀的數(shù)據(jù),這樣就可以做到一邊顯示一邊處理下一幀的數(shù)據(jù)批幌。


前面的幀用序號(hào)表示础锐,但實(shí)際上幀數(shù)據(jù)只保存在A、B兩個(gè)緩沖區(qū)中荧缘。當(dāng)前幀顯示緩沖A皆警,Android系統(tǒng)一旦發(fā)出VSYN信號(hào)時(shí),就會(huì)在緩沖B中構(gòu)建新的幀截粗。當(dāng)完成后(這里的完成指的是屏幕已經(jīng)在緩沖B中拿到新一幀的數(shù)據(jù)信姓,完成繪制),緩沖A的數(shù)據(jù)就會(huì)被清空桐愉,繼續(xù)進(jìn)行下一幀的繪制财破,注意,此時(shí)緩沖B的數(shù)據(jù)是不會(huì)被清空的从诲,因?yàn)楫?dāng)前顯示的是緩沖B中幀畫面左痢,清空的只是緩沖A的數(shù)據(jù)。
??這樣看起來貌似沒什么問題系洛,一切都是我們的掌控中俊性。但是,由于某些原因描扯,比如我們應(yīng)用代碼上處理不夠好定页,又或者用戶手機(jī)后臺(tái)打開了很多應(yīng)用,又在聽歌又在下載視頻什么的绽诚,CPU一時(shí)間被占用了典徊,導(dǎo)致下一幀繪制的時(shí)間超過了16ms,那么問題就來了恩够,這時(shí)候用戶就不爽了卒落,因?yàn)橛脩艉苊黠@感知到了卡頓的出現(xiàn),也就是所謂的丟幀情況蜂桶。如下圖所示:

很好儡毕,下面我們來認(rèn)真分析一下為什么會(huì)出現(xiàn)丟幀的情況:

Step1. 當(dāng)Display顯示第0幀數(shù)據(jù),此時(shí)CPU和GPU已經(jīng)開始渲染第1幀畫面扑媚,并將數(shù)據(jù)緩存在緩沖B中腰湾;

Step2. 但是由于某些原因雷恃,就好像上面說的,CPU資源一時(shí)間被占用费坊,導(dǎo)致系統(tǒng)處理該幀數(shù)據(jù)耗時(shí)過長或者未能及時(shí)處理該幀數(shù)據(jù)倒槐;

Step3. 當(dāng)VSYNC信號(hào)來時(shí),display向B緩沖要數(shù)據(jù)葵萎,這下悲催了导犹,因?yàn)榫彌_B的數(shù)據(jù)還沒準(zhǔn)備好,B緩沖區(qū)這時(shí)候是被鎖定的羡忘,display無可奈何,只能繼續(xù)顯示之前緩沖A的那一幀磕昼,此時(shí)緩沖A的數(shù)據(jù)也不能被清空和交換數(shù)據(jù)卷雕。這種情況被Android開發(fā)組命名為“Jank”,就是所謂的“丟幀”票从,也被稱作“廢幀”漫雕;

Step4. 當(dāng)?shù)?幀數(shù)據(jù)(即緩沖B數(shù)據(jù))準(zhǔn)備完成后,它并不會(huì)馬上被顯示峰鄙,而是要等待下一個(gè)VSYNC浸间,Display刷新后,這時(shí)用戶才看到畫面的更新吟榴,中間這段時(shí)間的時(shí)間就白白被浪費(fèi)掉了魁蒜。

從上面的分析可以知道,因?yàn)榫彌_B的超時(shí)吩翻,掉了鏈子兜看,導(dǎo)致出現(xiàn)了丟幀的情況。因?yàn)橐徊降难舆t狭瞎,也很有可能導(dǎo)致后面的處理延遲细移,很可能造成一步慢步步慢啊。

三倍緩沖機(jī)制

出現(xiàn)上面這種情況怎么辦熊锭,在Android系統(tǒng)里給出了這樣的解決辦法就是:再加入一個(gè)緩沖弧轧。這樣就出現(xiàn)了三個(gè)緩沖,顧名思義碗殷,這里說的就是三倍緩沖精绎。好,看下圖:


當(dāng)出現(xiàn)B緩沖超時(shí),屏幕顯示的還是緩沖A中的那一幀亿扁,因?yàn)榇藭r(shí)緩沖A的數(shù)據(jù)還在使用捺典,不能及時(shí)被交換,所以在下一次VSYNC信號(hào)來之前這段時(shí)間無任何作為从祝,時(shí)間就會(huì)白白被浪費(fèi)襟己。為了避免這種時(shí)間浪費(fèi)引谜,在三倍緩沖機(jī)制中,系統(tǒng)這個(gè)時(shí)候會(huì)創(chuàng)建一個(gè)緩沖C擎浴,用來緩沖下一幀的數(shù)據(jù)员咽。如上圖所示,顯示完緩沖B中那一幀后贮预,下一幀就是顯示緩沖C中的了贝室。這樣雖然還是不能避免會(huì)出現(xiàn)卡頓的情況,但是Android系統(tǒng)還是盡力去彌補(bǔ)這種缺陷仿吞,最終盡可能給用平滑的動(dòng)效體驗(yàn)滑频。

Overdraw解決方法

Overdraw(過度繪制)描述的是屏幕上的某個(gè)像素在同一幀的時(shí)間內(nèi)被繪制了多次。在多層次的UI結(jié)構(gòu)里面唤冈,如果不可見的UI也在做繪制的操作峡迷,這就會(huì)導(dǎo)致某些像素區(qū)域被繪制了多次。這就浪費(fèi)大量的CPU以及GPU資源你虹。

1. 使用HierarchyViewer來查找Activity中的布局是否過于復(fù)雜
2. 打開Show GPU Overdraw的選項(xiàng)绘搞,觀察UI上的Overdraw情況


藍(lán)色,淡綠傅物,淡紅夯辖,深紅代表了4種不同程度的Overdraw情況,我們的目標(biāo)就是盡量減少紅色Overdraw董饰,看到更多的藍(lán)色區(qū)域蒿褂。

Overdraw有時(shí)候是因?yàn)槟愕腢I布局存在大量重疊的部分,還有的時(shí)候是因?yàn)榉潜仨毜闹丿B背景尖阔。例如某個(gè)Activity有一個(gè)背景贮缅,然后里面的Layout又有自己的背景,同時(shí)子View又分別有自己的背景介却。僅僅是通過移除非必須的背景圖片谴供,這就能夠減少大量的紅色Overdraw區(qū)域,增加藍(lán)色區(qū)域的占比齿坷。這一措施能夠顯著提升程序性能桂肌。

3. 使用TraceView來觀察CPU的執(zhí)行情況,更加快捷的找到性能瓶頸
4. Profile GPU Rendering永淌,選中On screen as bars選項(xiàng)
選擇了這樣以后崎场,我們可以在手機(jī)畫面上看到豐富的GPU繪制圖形信息,分別關(guān)于StatusBar遂蛀,NavBar谭跨,激活的程序Activity區(qū)域的GPU Rending信息。

中間有一根綠色的橫線,代表16ms螃宙,我們需要確保每一幀花費(fèi)的總時(shí)間都低于這條橫線蛮瞄,這樣才能夠避免出現(xiàn)卡頓的問題。

參考資料:

http://www.csdn.net/article/2015-01-20/2823621-android-performance-patterns/1
http://www.reibang.com/p/02800806356c
https://www.youtube.com/watch?v=HXQhu6qfTVU&list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE&index=58
http://www.reibang.com/p/1fb065c806e6

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末谆扎,一起剝皮案震驚了整個(gè)濱河市挂捅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌堂湖,老刑警劉巖闲先,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異无蜂,居然都是意外死亡伺糠,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門酱讶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來退盯,“玉大人,你說我怎么就攤上這事泻肯。” “怎么了慰照?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵灶挟,是天一觀的道長。 經(jīng)常有香客問我毒租,道長稚铣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任墅垮,我火速辦了婚禮惕医,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘算色。我一直安慰自己抬伺,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布灾梦。 她就那樣靜靜地躺著峡钓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪若河。 梳的紋絲不亂的頭發(fā)上能岩,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音萧福,去河邊找鬼拉鹃。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的膏燕。 我是一名探鬼主播钥屈,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼煌寇!你這毒婦竟也來了焕蹄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤阀溶,失蹤者是張志新(化名)和其女友劉穎腻脏,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體银锻,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡永品,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了击纬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鼎姐。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖更振,靈堂內(nèi)的尸體忽然破棺而出炕桨,到底是詐尸還是另有隱情,我是刑警寧澤肯腕,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布献宫,位于F島的核電站,受9級(jí)特大地震影響实撒,放射性物質(zhì)發(fā)生泄漏姊途。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一知态、第九天 我趴在偏房一處隱蔽的房頂上張望捷兰。 院中可真熱鬧,春花似錦负敏、人聲如沸贡茅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽友扰。三九已至,卻和暖如春庶柿,著一層夾襖步出監(jiān)牢的瞬間村怪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國打工浮庐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留甚负,地道東北人柬焕。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像梭域,于是被迫代替她去往敵國和親斑举。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

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