1.圖像顯示原理簡介
有關概念:
時鐘信號:垂直同步信號V-Sync / 水平同步信號H-Sync
iOS設備雙緩沖機制:前/后幀緩沖區(qū)
1.CPU和GPU通過總線連接起來,工作流程如上圖示:
在CPU中的工作完成會生成一個位圖(bitmap),位圖再經(jīng)由總線在合適的時機上傳給GPU處理,GPU拿到位圖之后會進行相應位圖的圖層渲染(頂點變換、紋理混合等操作),之后會把結果放到幀緩沖區(qū)(Frame Buffer)中,由視屏控制器根據(jù)Vsync信號,在指定時間前提取對應幀緩沖區(qū)中的屏幕顯示內(nèi)容,最終顯示到手機屏幕上。
2.UI視圖顯示到屏幕上的大概流程如上圖示:創(chuàng)建一個UIView,它的顯示部分是由CALayer負責的,CALayer有一個contents屬性(即最終要繪制到屏幕上的位圖),比如說創(chuàng)建的是一個顯示“Hello world”的UILable,那么contents中放置的結果就是一個關于"Hello world"的文字位圖。另外系統(tǒng)會在合適的時機回調(diào)一個drawRect:方法,在此基礎上我們就可以繪制一些想要自定義的內(nèi)容,繪制好的位圖,會經(jīng)由CoreAnimation框架,提交給GPU部分的OpenGL渲染管線進行位圖的渲染,最終顯示到屏幕上。
3.CPU工作:負責UI布局、文本計算,繪制,圖片解碼,繪制紋理交給GPU

4.GPU工作:紋理混合,頂點變換,渲染到幀緩沖區(qū)
2.UI掉幀、卡頓原因
1.通常來說頁面滑動的流暢性是60fps(指每一秒會有60幀畫面更新),人眼看到的是流暢的效果。也因此每隔 s(即16.7ms)就要產(chǎn)生一幀畫面,也就是說在這16.7ms時間內(nèi)GUP和CPU要協(xié)同完成產(chǎn)生一幀的數(shù)據(jù),比如CPU花了一定的時間做UI布局、文本計算、視圖的繪制和圖片解碼,并把產(chǎn)生的位圖提交給GPU,GPU又要花一定的時間進行紋理混合渲染,然后在下一幀的VSync垂直信號到來之前顯示這一幀畫面。

在上圖中,如果CPU和GPU協(xié)同工作的時間在16.7ms內(nèi),那么圖像的顯示是流暢的;如果CPU花費了大量時間來做frame的布局、視圖繪制和圖片解碼,那么留給GPU的時間就不多了,GPU要想把圖層合成、紋理渲染全部完成就要超過16.7ms,那么在下一幀的垂直信號VSync到來之前,還沒有準備好當前的一幀畫面,這就產(chǎn)生了掉幀,體現(xiàn)在滑動上的就是上下滑動卡頓的效果。
總而言之,在規(guī)定的16.7ms內(nèi),CPU和GPU并沒有在下一幀的Vsync信號到來之前把當前的一幀畫面生產(chǎn)完成,由此產(chǎn)生了掉幀卡頓。
2.滑動優(yōu)化方案
CPU資源消耗分析
?對象創(chuàng)建:對象的創(chuàng)建會分配內(nèi)存、調(diào)整屬性、甚至還有讀取文件等操作,比較消耗CPU資源。盡量采取輕量級對象,盡量放到后臺線程處理,盡量推遲對象的創(chuàng)建時間。(如UIView? /? CALayer)
?對象調(diào)整:frame、bounds、transform及視圖層次等屬性調(diào)整很耗費CPU資源。盡量減少不必要屬性的修改,盡量避免調(diào)整視圖層次、添加和移除視圖。
?布局計算:隨著視圖數(shù)量的增長,Autolayout帶來的CPU消耗會呈指數(shù)級增長,所以盡量提前算好布局,在需要時一次性調(diào)整好對應屬性。
?文本渲染:屏幕上能看到的所有文本內(nèi)容控件,包括UIWebView,在底層都是通過CoreText排版、繪制為位圖顯示的。常見的文本控件,其排版與繪制都是在主線程進行的,顯示大量文時是,CPU壓力很大。對此解決方案唯一就是自定義文本控件,用CoreText對文本異步繪制。(很麻煩,開發(fā)成本高)
?圖片解碼:當用UIImage或CGImageSource創(chuàng)建圖片時,圖片數(shù)據(jù)并不會立刻解碼。圖片設置到UIImageView或CALayer.contents中去,并且CALayer被提交到GPU前,CGImage中的數(shù)據(jù)才會得到解碼。這一步是發(fā)生在主線程的,并且不可避免。SD_WebImage處理方式:在后臺線程先把圖片繪制到CGBitmapContext中,然后從Bitmap直接創(chuàng)建圖片。
?圖像繪制:圖像的繪制通常是指用那些以CG開頭的方法把圖像繪制到畫布中,然后從畫布創(chuàng)建圖片并顯示的一個過程。CoreGraphics方法是線程安全的,可以異步繪制,主線程回調(diào)。
GPU資源消耗分析
?紋理渲染:盡量減少短時間內(nèi)大量圖片的顯示,盡可能將多張圖片合成一張進行顯示。
?視圖混合:盡量減少視圖層次和數(shù)量,并在不透明的視圖里標明opaque屬性以避免無用的Alpha通道合成。
?圖形生成:盡量避免離屏渲染,盡量采用異步繪制,盡量避免使用圓角、陰影、遮罩等屬性。必要時用靜態(tài)圖片實現(xiàn)展示效果,也可嘗試光柵化緩存復用屬性。
基于上述的分析保持界面流暢,優(yōu)化的時候就要從CPU和GPU兩方面考慮。
優(yōu)化參考iOS如何優(yōu)化項目
3.離屏渲染
1.有關概念:
?On-Screen-Rendering: 意為當前屏幕渲染,指的是GPU的渲染操作是在當前用于顯示的屏幕緩沖區(qū)中進行
?Off-Screen-Rendering: 離屏渲染,指的是GPU在當前屏幕緩沖區(qū)以外新開辟一個緩沖區(qū)進行渲染操作
CPU渲染及非GPU緩沖區(qū)的渲染統(tǒng)稱為離屏渲染
2.離屏渲染消耗性能的原因
?需要創(chuàng)建新的緩沖區(qū)
?離屏渲染的整個過程,需要多次切換上下文環(huán)境,先是從當前屏幕(On-Screen)切換到離屏(Off-Screen);等到離屏渲染結束以后,將離屏緩沖區(qū)的渲染結果顯示到屏幕上,又需要將上下文環(huán)境從離屏切換到當前屏幕
3.何時會觸發(fā)?
?圓角(當和masksToBounds或者clipsToBounds為YES一起使用時)(對于UIimageview的圓角iOS9之后做了優(yōu)化,在不加背景顏色的情況下,同時設置兩者不會觸發(fā)離屏渲染。但是UIButton等控件依然會觸發(fā),考慮通過 CoreGraphics 繪制裁剪image矩形圓角,或者叫美工提供圓角圖片)
?圖層蒙版 (layer.mask)? 無法取消離屏渲染
?抗鋸齒(edgeAntialiasing)
?陰影 (layer.shadowXXX,如果設置了 layer.shadowPath 就不會產(chǎn)生離屏渲染)可以通過指定路徑來取消離屏渲染
?不透明(GroupOpacity)
?光柵化 (layer.shouldRasterize置為YES)
4.檢測離屏渲染
模擬器:Debug->Color Offscreen-Rendered離屏渲染的圖層高亮成黃,可能存在性能問題真機:Xcode->Debug->View Debugging->Rendering->選中 Color Offscreen-Rendered Yellow? 或者?? Instrument->Core Animation->選中 Color Offscreen-Rendered Yellow
5.光柵化
光柵化簡介:隱式創(chuàng)建一個位圖,各種陰影遮罩等效果也會保存到位圖中緩存起來,從而減少渲染的頻度,把GPU的操作轉到CPU上,生成位圖緩存,直接讀取調(diào)用。(注:對于經(jīng)常變動的內(nèi)容,不要開啟光柵化,防止性能浪費,如Cell的復用)
光柵化的檢測:Color Hits Green and Misses Red 開啟后,若shouldRasterize設置為YES,對應的渲染結果會緩存,如果圖層是綠色,表示緩存被復用;如果是紅色,就表示緩存被重復創(chuàng)建,可能存在性能問題。
任何時候優(yōu)先考慮避免觸發(fā)離屏渲染,無法避免時優(yōu)化方案有兩種:
?Rasterization:適用于靜態(tài)內(nèi)容的視圖,也就是內(nèi)部結構和內(nèi)容不發(fā)生變化的視圖,對上面的所有效果而言,在實現(xiàn)成本以及性能上最均衡的。即使是動態(tài)變化的視圖,開啟 Rasterization 后能夠有效降低 GPU 的負荷,不過在動態(tài)視圖里是否啟用還是看 Instruments 的數(shù)據(jù)。
?規(guī)避離屏渲染,用其他手法來模擬效果,混合圖層是個性能最好、耗能最少的通用優(yōu)化方案,尤其對于 rounded corer 和 mask
關于離屏渲染觸發(fā)及優(yōu)化可以看下面的文章:
4.圖像撕裂
圖像撕裂原因:當視頻控制器還未讀取完成時,GPU將新的一幀內(nèi)容提交到幀緩沖區(qū)并把兩個幀緩沖區(qū)進行更新后,視頻控制器就會把新的一幀數(shù)據(jù)的下半段顯示到屏幕上,造成畫面撕裂的現(xiàn)象。
?解決方案:垂直同步機制
?弊端:GPU會等待顯示的V-Sync信號發(fā)出后,才進行新的一幀渲染和緩存區(qū)更新。能解決畫面撕裂現(xiàn)象,也增加了畫面流暢度,但需要消耗更多的計算資源,由此可能導致卡頓。
參考文章ios圖像顯示原理
Texture相關參考資料
官方文檔:http://texturegroup.org/docs/getting-started.html
官方文檔部分譯文一:https://juejin.im/post/5a16acf56fb9a04509092ce5
官方文檔部分譯文二(布局系統(tǒng)):https://juejin.im/post/5a1be41351882561a20a32e9#heading-17
即刻技術團隊關于ASDK:
一、https://zhuanlan.zhihu.com/p/25371361
二、https://zhuanlan.zhihu.com/p/26283742
三、https://zhuanlan.zhihu.com/p/29537687
iOS 保持界面流暢的技巧:https://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/
ASDK源碼剖析:http://beelearning.cn/2017/11/ASDK/
從 Auto Layout 的布局算法談性能 :https://draveness.me/layout-performance