iOS显示性能优化过程讲解
點我跳轉(zhuǎn)原文地址
卡頓的原理
iOS系統(tǒng)界面滑動流暢性的保持主要是依靠CPU和GPU兩大處理硬件間通力合作的結(jié)果,一個視圖的顯示需要先經(jīng)過CPU創(chuàng)建、布局計算、對圖片解碼、文本繪制,然后CPU將計算的結(jié)果交給GPU,GPU可能需要對圖形進行變換、合成、渲染,GPU然后將渲染的結(jié)果提交到幀緩沖區(qū)等待下一次的垂直同步信號(V-Sync)到來顯示到顯示器上,如果在一個V-Sync間隔內(nèi)CPU或者GPU由于過高的利用率都可能導(dǎo)致數(shù)據(jù)的不及時提交,那么那一幀數(shù)據(jù)就會被丟棄,等待下一次的V-Sync再顯示,這也就是通常能感受到的界面卡頓現(xiàn)象,也就是掉幀。
優(yōu)化過程
所以當(dāng)出現(xiàn)卡頓現(xiàn)象時主要去分析此刻CPU和GPU的利用率,當(dāng)出現(xiàn)較高的CPU利用率時應(yīng)及時去分析代碼執(zhí)行的效率,或者用Time Profier去分析導(dǎo)致較高占用率的代碼,更多詳細的關(guān)于優(yōu)化CPU的情況本文不做詳細分析。
而對于GPU資源消耗的優(yōu)化本文將通過一個Demo優(yōu)化過程來講解優(yōu)化的步驟,你可以在這里GitHub下載源碼,Demo是有2個tab組成的,before是優(yōu)化前視圖,after是優(yōu)化后的,你可以通過對比學(xué)習(xí)體會其中的差異。
下載運行demo, 打開Xcode的調(diào)試選項,在菜單欄-Debug-View Debugging-Rendering可以找到,運行APP(真機)勾選相關(guān)的菜單選項即可
1.視圖混合(Blending)
app中顯示的效果往往是多個視圖重合疊加的效果,而在計算視圖重合顯示顏色的時候就需要考慮透明的影響,當(dāng)頂部視圖出現(xiàn)透明的情況時,顏色的計算就需要考慮其透明度,這樣無疑增加了計算成本,消耗GPU資源,所以應(yīng)盡量避免過多的透明視圖數(shù)量。
對于UIImageView而言,如果圖片本身是帶有透明通道的同樣會導(dǎo)致Blending,所以應(yīng)該盡量避免使用帶有透明度的圖片。
對于文本UILable, 如果不設(shè)置背景顏色,同樣會出現(xiàn)Blending,所以需要設(shè)置UILabel的背景顏色,對于顯示中文的UILabel, 除了設(shè)置背景顏色外還需要設(shè)置masksToBounds屬性,因為中文時UILable會多了一個sublayer。
勾選Rendering中的第一個選項Color Blended Layers,此選項就是用于檢測哪些視圖出現(xiàn)了Blending,出現(xiàn)Blending的地方會用紅色標(biāo)記出來,運行demo可以出現(xiàn)下圖所示情況:
可以看到,before tab下的控制器視圖無論是圖片還是文本都被標(biāo)紅,表示出現(xiàn)了Blending,對于圖片我們可以在Assets里面找到對應(yīng)的圖片,然后查看簡介就可以查看圖片是否有Alpha通道,會看到圖片都具有Alpha通道,也就回導(dǎo)致Blending
對于這種情況,可以讓UI切圖時關(guān)閉此Alpha通道,也可以直接用mac自帶的圖片軟件打開圖片,然后導(dǎo)出圖片關(guān)閉Alpha通道。所以我們需要將所有有Alpha的圖片都處理一遍,盡量不要使用帶有透明度的圖片。
對于UILabel,上面有提到,我們只需要下面的2行代碼即可處理:
通過去掉圖片alpha通道優(yōu)化后如下圖所示,只有被設(shè)置為圓角的小圖片還存在Blending,因為我們是直接設(shè)置的layer的cornerRadius(IOS9以下會導(dǎo)致離屏渲染),同樣我們可以直接用無透明通道的圓角圖片來替換解決,但這需要UI適配更多背景圖片。
2.光柵化
開啟光柵化是通過設(shè)置屬性shouldRasterize,開啟光柵化后CALayer會被保存為bitmap放到緩存中,這樣在下次需要時可以直接中緩存中取出來顯示,這樣節(jié)省了渲染時間,例如對于設(shè)置有陰影效果的復(fù)雜視圖會對性能有一定的提升。
nameLabel.layer.shouldRasterize = true//開啟光柵化第二個調(diào)試選項 Color Hits Green and Misses Red就是用來查看光柵化視圖的,勾選后若視圖被標(biāo)記為綠色,則表示命中了緩存,直接從緩存中取出來顯示,緩存的有效時間為100ms, 而紅色則表示沒有命中。Demo中,我們對第2個Label開啟了光柵化,滾動會發(fā)現(xiàn)被標(biāo)記為綠色
更新一個已光柵化的Layer會觸發(fā)離屏渲染,所以選擇哪些視圖適合做光柵化需要根據(jù)場景權(quán)衡,光柵化適合那些布局復(fù)雜而不經(jīng)常變動的視圖,比如
- 用于避免靜態(tài)內(nèi)容的復(fù)雜特效的重繪,例如UIBlurEffect
- 用于避免多個View嵌套的復(fù)雜View的重繪。
同時注意緩存是有大小限制的,所以不要過度是使用光柵化,因為超過緩存大小會導(dǎo)致大量的離屏渲染。
3.顏色格式
Color Copied Images選項能標(biāo)識出視圖中不能被GPU處理的圖片,因為來自網(wǎng)絡(luò)的圖片格式可能千變?nèi)f化,有的圖片的格式是GPU無法識別的所以會交給CPU處理,出現(xiàn)這種情況就需要修改圖片格式,
4.不標(biāo)準的表面顏色格式
Color Non-Standard Surface Formats 打開此選項后會發(fā)現(xiàn)Label會出現(xiàn)灰色的背景顏色,然后經(jīng)過我們給Label設(shè)置了背景顏色后便消失了,關(guān)于此選項的相關(guān)介紹甚少,期待有人能挖掘挖掘,所以只能猜測,蘋果推薦我們給Label設(shè)置一個背景顏色。
5.顏色刷新頻率
默認情況下圖層的顏色更新是有10ms的延遲的,在某些特定情況下可能需要關(guān)閉這個延遲,但絕大多數(shù)情況用不到這個選項。
6.圖片大小
Color Misaligned Images選項在圖片像素不對齊(也就是圖片帶alpha通道)時,會在圖片上面加一層洋紅色來標(biāo)識;而圖片被縮放時,會加一層黃色來標(biāo)識,我們可以看到優(yōu)化前的圖片會出現(xiàn)圖片縮放,因為圖片的顯示大小和圖片的大小不匹配。
圖片縮放同樣會消耗GPU資源,所以盡量保證圖片的顯示大小和原圖大小一致來避免縮放,所以demo的圖片在處理后大小都等于顯示的大小來避免縮放。
7.離屏渲染
Color Offscreen-Rendered Yellow會用黃色標(biāo)識哪些圖層出現(xiàn)了離屏渲染,什么是離屏渲染?
離屏渲染表示渲染不是發(fā)生在當(dāng)前屏幕的緩沖區(qū)中,而是發(fā)生在其他緩沖區(qū)的渲染,這就需要開辟更多的緩沖區(qū),等到要用的時候再從其他的緩沖區(qū)讀取來顯示,所以這樣會消耗更多的GPU資源,所以避免離屏渲染可以有效的提升顯示性能。
如上圖所示,要顯示一個相機圖標(biāo)和一個蒙層,在前兩個渲染通道中,GPU分別得到了相機的紋理和藍色的蒙版layer的渲染結(jié)果。但這兩個渲染結(jié)果沒有直接放入Frame Buffer中,這就是離屏渲染。等到第三個渲染通道,才把兩者組合起來放入Frame Buffer中最終顯示到屏幕上,這就是典型的離屏渲染。
運行demo,打開Color Offscreen-Rendered Yellow選項,在beforetab控制器視圖下出現(xiàn)離屏渲染的圖層便會被黃色標(biāo)識出來,如圖:
可以發(fā)現(xiàn)右邊的大圖出現(xiàn)了離屏渲染,而圓角的小圖卻沒有,大圖出現(xiàn)離屏渲染的原因是設(shè)置了shadow陰影,而因為測試機器是ios11所以設(shè)置圖片的cornerRadius并不會導(dǎo)致離屏渲染。
同樣設(shè)置了以下屬性時,都會觸發(fā)離屏渲染:
- shouldRasterize(光柵化)
- masks(遮罩)
- shadows(陰影)
- edge antialiasing(抗鋸齒)
- group opacity(不透明)
- 復(fù)雜形狀設(shè)置圓角等(ios8)
- 漸變
上面出現(xiàn)離屏渲染的case都應(yīng)該要注意,所以針對shadow可以通過設(shè)置shadowPath來避免,光柵化也應(yīng)該盡量避免:
優(yōu)化后代碼如下:
8.快速路徑
第七個選項“Color Compositing Fast-Path Blue”用于標(biāo)記由硬件繪制的路徑,藍色越多越好,demo略
9.變化區(qū)域
最后一個Flash Updated Regions 用于標(biāo)記發(fā)生重繪制的區(qū)域并用黃色標(biāo)記出來,對于大多數(shù)不變的區(qū)域應(yīng)該盡量的避免重繪而只有小部分經(jīng)常變化的區(qū)域重繪這有助于顯著提高性能。demo略
優(yōu)化結(jié)果
經(jīng)過對圖片Alpha透明度調(diào)整,大小剪裁適配顯示,更改設(shè)置陰影,文本背景等一系列的優(yōu)化,使用Core Animation記錄GPU使用率的變化來觀察優(yōu)化效果:
before:
可以看到優(yōu)化前CPU平均占用率達到60%,這還只是簡單的視圖布局,如果更加復(fù)雜占用率還會增加,這也就意味著更高的卡頓風(fēng)險。
after:
對比可以發(fā)現(xiàn)在提升了平均顯示幀數(shù)的同時大大降低了GPU消耗,性能得到顯著的提升。
測試環(huán)境:Xcode9.3、iPhone6s、 iOS11、Swift4
Demo地址:GitHub地址
總結(jié)
以上是生活随笔為你收集整理的iOS显示性能优化过程讲解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【阅读推荐】改变你思维模式的书单
- 下一篇: 光谱 波长_【第三课】红外光谱仪及其联用