渲染性能優(yōu)化

多數(shù)情況下,卡頓發(fā)生的根本原因,是渲染問題拆宛,即系統(tǒng)無法及時的完成復(fù)雜界面的渲染操作。系統(tǒng)會嘗試每個16ms對UI進行渲染讼撒,如果每次都渲染成功浑厚,這樣畫面就是流暢的(達到了60fps);否則根盒,就會發(fā)生丟幀現(xiàn)象钳幅,丟幀越多,用戶感受到的卡頓情況就越嚴重炎滞。
為了獲得更平滑的動畫敢艰,就必須保證幀率不低于60fps——意味著每幀只能花費16毫秒的時間。

1册赛、一些概念

1钠导、刷新率vs幀率
  • 刷新率:每秒屏幕刷新次數(shù),手機屏幕的刷新率是60HZ
  • 幀率:GPU在一秒內(nèi)繪制的幀數(shù)
2森瘪、撕裂vs掉幀
  • 撕裂
    因為屏幕的刷新過程是自上而下牡属、自左向右的,如果幀率>刷新率扼睬,當屏幕還沒有刷新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進行渲染,如果你的某個操作花費時間是24ms官硝,系統(tǒng)在得到VSYNC信號的時候由于還沒有準備好,就無法進行更新任何內(nèi)容短蜕,那么用戶在32ms內(nèi)看到的會是同一幀畫面(卡頓現(xiàn)象)氢架,即丟幀現(xiàn)象。
丟幀
3朋魔、單緩存 vs VSYNC vs 雙緩存 vs 三緩存
  • 單緩存(沒有引入VSync )
    GPU向緩存中寫入數(shù)據(jù)岖研,屏幕從緩存中讀取數(shù)據(jù),刷新后顯示警检。由于刷新率和幀率并不總是一致的孙援,很可能導(dǎo)致撕裂的現(xiàn)象。為了解決單緩存的畫面撕裂問題扇雕,出現(xiàn)了雙緩存和 VSync 拓售。
    單緩存
  • VSYNC 和 雙緩存
    雙緩存使用了兩個緩存區(qū): Back Buffer 、 Frame Buffer镶奉。當寫入下一幀時础淤,GPU會先填充 Back Buffer 中,當刷新屏幕時哨苛,屏幕從 Frame Buffer 中讀數(shù)據(jù)鸽凶。VSYNC 主要是完成幀的復(fù)制,開始下一幀的渲染建峭。


    雙緩存

當幀率大于刷新頻率時玻侥,通過使幀率被迫跟刷新頻率保持同步,從而避免畫面撕裂的現(xiàn)象(只有當 VSync 信號產(chǎn)生時亿蒸, CPU/GPU 才會開始繪制)凑兰。當VSync 信號產(chǎn)生時,先完成Back Buffer 到 Frame Buffer的復(fù)制操作(通過交換內(nèi)存地址)祝懂,然后通知 CPU/GPU 繪制下一幀圖像票摇。也只有VSync 信號發(fā)生時,才繪制下一幀砚蓬。

VSYNC 和 雙緩存

當刷新頻率>幀率時矢门,此時刷新屏幕,發(fā)出VSYNC 信號,由于CPU/GPU的渲染操作還沒有完成祟剔,就不把Back Buffer的數(shù)據(jù)復(fù)制到 Frame Buffer隔躲,此時就從Frame Buffer去取舊數(shù)據(jù),這樣在兩個刷新周期里物延,顯示的是同一幀數(shù)據(jù)宣旱, 掉幀

  • 三重緩存


    三緩存

    雙重緩存的缺陷在于:當 CPU/GPU 繪制一幀的時間超過 16 ms 時,會產(chǎn)生 Jank叛薯。更要命的是浑吟,產(chǎn)生 Jank 的那一幀的顯示期間,GPU/CPU 都是在閑置的耗溜。
    如下圖组力,A、B 和 C 都是 Buffer抖拴。

雙重緩存

如果有第三個 Buffer 能讓 CPU/GPU 在這個時候繼續(xù)工作燎字,那就完全可以避免第二個 Jank 的發(fā)生了!

三重緩存

2阿宅、渲染是怎么實現(xiàn)的

如何把布局渲染成用戶可以識別的圖片候衍?它的核心是通過柵格化操作,將一些按鈕洒放、文字等布局對象拆分到像素點進行顯示蛉鹿。由于柵格化是非常費時的,因此引入了GPU加快柵格化過程拉馋。

整個處理過程是:CUP負把把UI對象轉(zhuǎn)變GPU可以識別的成圖元(多邊形榨为、紋理),然后上傳到GPU進行柵格化過程煌茴。


渲染的過程
1随闺、在GPU中保存圖元

但是由于這個轉(zhuǎn)換、上傳都是耗時的蔓腐,所以為了減少時間矩乐,需要減少它們的數(shù)量,慶幸的是Open GL API回论,允許你將這些圖元保存到GPU散罕,當下次需要一個按鈕的時候,只要參考GPU中已經(jīng)存在的圖元傀蓉,告訴GPU如何去繪制 它欧漱。優(yōu)化渲染性能就意味著盡可能多且快的將更多的數(shù)據(jù)上傳到GPU,然后留在GPU葬燎,盡可能長時間的不去修改它误甚。


轉(zhuǎn)換缚甩、上傳耗時

將圖元保存到GPU

2、display list窑邦,CPU擅威、GPU溝通的橋梁

將圖元從CPU上傳到GPU,這個操作是在DisplayList的幫助下完成的冈钦。DisplayList持有GPU渲染時需要的信息郊丛,包括了一些圖元和Open GL命令列表。

CPU直接與GPU通信瞧筛,而是通過中間的一個圖形驅(qū)動層(Graphics Driver)來連接這兩部分厉熟。 圖形驅(qū)動維護了一個隊列,CPU把display list添加到隊列里驾窟,GPU從這個隊列取出數(shù)據(jù)進行繪制庆猫。

Display List,在View第一次需要被渲染時被創(chuàng)建绅络,當這個View要顯示到屏幕上時,我們會執(zhí)行GPU的繪制指令來執(zhí)行這個Display List嘁字。

CUP 工作
GPU

整體流程是:CUP負把把UI對象轉(zhuǎn)變GPU可以識別的成圖元(多邊形恩急、紋理),并存儲進display list列表纪蜒;GPU執(zhí)行繪圖指令來執(zhí)行display list衷恭,取出相應(yīng)的圖元信息,進行柵格化渲染

3纯续、引起的原因和檢測方法

主要有以下幾點随珠,可能引起渲染的性能問題:

  • 布局Layout過于復(fù)雜,無法在16ms內(nèi)完成渲染猬错。
  • 同一時間動畫執(zhí)行的次數(shù)過多窗看,導(dǎo)致CPU或GPU負載過重。
  • View過度繪制倦炒,導(dǎo)致某些像素在同一幀時間內(nèi)被繪制多次显沈。
  • UI線程中做了稍微耗時的操作。

可以通過如下工具進行檢測
HierarchyViewer(布局盡量扁平化)逢唤、Show GPU Overdraw拉讯、Profile GPU Rendering等等

1、Profile GPU Rendering

1鳖藕、打開手機里面的開發(fā)者選項魔慷,選擇Profile GPU Rendering,選中On screen as bars的選項

通過Profile GPU Rendering著恩,可以在屏幕上實時顯示渲染每一幀圖像花費的時間院尔。渲染時間用柱狀圖表示蜻展,每一條柱狀圖都由3部分組成,藍色召边、紅色和黃色铺呵,代表渲染的3個不同的階段,通過分析這三個階段的時間就可以找到渲染時的性能瓶頸隧熙。

Profile GPU Rendering
2片挂、使用命令
adb shell dumpsys gfxinfo yourpackagename
命令

命令

將得到的數(shù)據(jù)保存為txt,之后導(dǎo)出到excel(數(shù)據(jù)-導(dǎo)入數(shù)據(jù))贞盯,生成圖表

fps圖表

Draw:表示在Java中創(chuàng)建顯示列表部分中音念,OnDraw()方法占用的時間。
Process:表示渲染引擎執(zhí)行顯示列表所花的時間躏敢,view越多闷愤,時間就越長
Execute:表示把一幀數(shù)據(jù)發(fā)送到屏幕上排版顯示實際花費的時間。其實是實際顯示幀數(shù)據(jù)的后臺緩存區(qū)與前臺緩沖區(qū)交換后并將前臺緩沖區(qū)的內(nèi)容顯示到屏幕上的時間件余。所以這個時間讥脐,一般都很短。
Draw + Process + Execute = 完整顯示一幀 啼器,這個時間要小于16ms才能保存每秒60幀(即1000秒/60幀)旬渠。   
將數(shù)據(jù)復(fù)制到 excel中,然后將數(shù)據(jù)生成“柱形圖”來觀察結(jié)果端壳。

參考:Android性能專項FPS測試實踐

3告丢、通過Android Studio的GPU Monitor查看
Android Studio的GPU Monitor
4、分析

隨著界面的刷新损谦,界面上會滾動顯示垂直的柱狀圖來表示每幀畫面所需要渲染的時間岖免,柱狀圖越高表示花費的渲染時間越長。中間有一根綠色的橫線照捡,代表16ms颅湘,我們需要確保每一幀花費的總時間都低于這條橫線菲宴,這樣才能夠避免出現(xiàn)卡頓的問題置鼻。
每一條柱狀線都都包含三部分

  • 藍色代表測量繪制Display List的時間,是CPU將UI對象轉(zhuǎn)變成圖元说莫,并緩存在display list的時間
    視圖(display list )突然無效了
  • 紅色是GPU執(zhí)行渲染指令术羔,使用OpenGL執(zhí)行Display List的時間
    view過于復(fù)雜或繪制多次
  • 黃色代表CPU等待GPU處理的時
    GPU做了太多的工作

總之赢赊,布局層次過深,view過于復(fù)雜都會導(dǎo)致時間過長

Android 4.0-5.0的柱狀條
Android 6.0以上的柱狀條

Swap Buffers(黃色):CPU等待GPU的時間
Command Issue(紅色):OpenGL繪制display list的時間
Sync/upload(淺藍色):代表上傳bitmap到GPU的時間级历,如果值比較大释移,是因為花費了相當多的時間價值大量圖片。
Draw(藍色):創(chuàng)建和更新display list的時間
Misc Time/Vsync Delay(深綠):在兩個連續(xù)的幀之間執(zhí)行的操作寥殖,如果很大玩讳,可能因為在UI線程做了太多的工作涩蜘。
Input Handling(淺綠):處理用戶的輸入事件,花費的時間
Animation(淺淺綠):在當前幀中的動畫 花費了的時間

2熏纯、過度繪制

過度繪制(Overdraw)是屏幕上的某個像素在同一幀的時間內(nèi)被繪制了多次同诫。可以在開發(fā)者選項中打開 Show GPU Overdraw樟澜,觀察過度繪制情況误窖。


過度繪制

如果沒有顏色,代表沒有過度繪制秩贰,藍色霹俺,淡綠,淡紅毒费,深紅代表了4種不同程度的Overdraw情況丙唧,分別表示了對應(yīng)的像素被多繪制了1、2觅玻、3想际、4次,應(yīng)當盡量減少紅色區(qū)域溪厘。

過度繪制可能是因為組件的互相重疊或者不必要的背景重疊

組件的重疊沼琉,引起過度繪制
背景重疊,引起過度繪制

3桩匪、HierarchyViewer

1、打開Hierarchy Viewer

點擊 Tools>Android>Android Device Monitor友鼻,選擇 Hierarchy Viewer傻昙,如下圖:


打開Android Device Monitor

選擇 Hierarchy Viewer

但是Hierachy Viewer默認是無法連接真機調(diào)試,只能使用模擬器了彩扔。但是要APP先運行起來再使用Android Device Monitor妆档。

HierachyViewer,翻墻了
2虫碉、分析頁面布局性能

選中一個節(jié)點贾惦,點擊 右上角,就可以獲取到布局繪制的時間敦捧,如圖


意義

從左到右依次须板,代表View的Measure, Layout和Draw的性能,不同顏色代表不同的性能等級:

  • 綠:該View的此項性能比該View Tree中超過50%的View都要快
  • 黃:該View的此項性能比該View Tree中超過50%的View都要慢
  • 紅:該View的此項性能是View Tree中最慢的

4.2 測量結(jié)果分析

紅色節(jié)點是代表應(yīng)用性能慢的一個潛在問題兢卵,下面是幾個例子习瑰,如何來分析和解釋紅點的出現(xiàn)原因?

1)如果在葉節(jié)點或者ViewGroup中秽荤,只有極少的子節(jié)點甜奄,這可能反映出一個問題柠横,應(yīng)用可能在設(shè)備上運行并不慢,但是你需要指導(dǎo)為什么這個節(jié)點是紅色的课兄,可以借助Systrace或者Traceview工具牍氛,獲取更多額外的信息;

2)如果一個視圖組里面有許多的子節(jié)點烟阐,并且測量階段呈現(xiàn)為紅色搬俊,則需要觀察下子節(jié)點的繪制情況;

3)如果視圖層級結(jié)構(gòu)中的根視圖曲饱,Messure階段為紅色悠抹,Layout階段為紅色,Draw階段為黃色扩淀,這個是比較常見的楔敌,因為這個節(jié)點是所有其它視圖的父類;

4)如果視圖結(jié)構(gòu)中的一個葉子節(jié)點驻谆,有20個視圖是紅色的Draw階段卵凑,這是有問題的,需要檢查代碼里面的onDraw方法胜臊,不應(yīng)該在那里調(diào)用勺卢。

  1. 布局常見問題與優(yōu)化建議

1)沒有用的父布局時指沒有背景繪制或者沒有大小限制的父布局,這樣的布局不會對UI效果產(chǎn)生任何影響象对。我們可以把沒有用的父布局黑忱,通過<merge/>標簽合并來減少UI的層次;

2)使用線性布局LinearLayout排版導(dǎo)致UI層次變深勒魔,如果有這類問題甫煞,我們就使用相對布局RelativeLayout代替LinearLayout,減少UI的層次;

3)不常用的UI被設(shè)置成GONE,比如異常的錯誤頁面冠绢,如果有這類問題抚吠,我們需要用<ViewStub/>標簽,代替GONE提高UI性能弟胀。

參考:Android 性能模式 第一季楷力、Android性能優(yōu)化典范 - 第1季Android性能優(yōu)化之渲染篇孵户、Android性能優(yōu)化系列——Profile GPU Rendering萧朝、Profile GPU Rendering WalkthroughAndroid 顯示原理簡介延届、Android 4.4 Graphic系統(tǒng)詳解(2) VSYNC的生成剪勿、理解 VSync了解Android 4.1方庭,之三:黃油項目 —— 運作機理及新鮮玩意
厕吉、Hierarchy Viewer使用詳解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末酱固,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子头朱,更是在濱河造成了極大的恐慌运悲,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件项钮,死亡現(xiàn)場離奇詭異班眯,居然都是意外死亡,警方通過查閱死者的電腦和手機烁巫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門署隘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人亚隙,你說我怎么就攤上這事磁餐。” “怎么了阿弃?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵诊霹,是天一觀的道長。 經(jīng)常有香客問我渣淳,道長脾还,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任入愧,我火速辦了婚禮鄙漏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘棺蛛。我一直安慰自己泥张,他們只是感情好,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布鞠值。 她就那樣靜靜地躺著,像睡著了一般渗钉。 火紅的嫁衣襯著肌膚如雪彤恶。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天鳄橘,我揣著相機與錄音声离,去河邊找鬼。 笑死瘫怜,一個胖子當著我的面吹牛术徊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鲸湃,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼赠涮,長吁一口氣:“原來是場噩夢啊……” “哼子寓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起笋除,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤斜友,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后垃它,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鲜屏,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年国拇,在試婚紗的時候發(fā)現(xiàn)自己被綠了洛史。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡酱吝,死狀恐怖也殖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情掉瞳,我是刑警寧澤毕源,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站陕习,受9級特大地震影響霎褐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜该镣,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一冻璃、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧损合,春花似錦省艳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至律适,卻和暖如春辐烂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背捂贿。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工纠修, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人厂僧。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓扣草,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子辰妙,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

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