CPU資源消耗的原因和解決方案
對(duì)象創(chuàng)建
*輕量對(duì)象代替重量對(duì)象
* 不需要響應(yīng)觸摸事件的控件:CALayer顯示
* 對(duì)象不涉及UI操作,則盡量放到后臺(tái)線程創(chuàng)建
* 包含有CALayer的控件只能在主線程創(chuàng)建和操作
* 通過(guò)Storyboard 創(chuàng)建視圖對(duì)象時(shí),其資源消耗會(huì)比直接通過(guò)代碼創(chuàng)建對(duì)象要大非常多,在性能敏感的界面里,storyboard不是一個(gè)好的技術(shù)選擇
* 盡量推遲對(duì)象創(chuàng)建的時(shí)間,并把對(duì)象的創(chuàng)建分散到多個(gè)任務(wù)中去。
* 對(duì)象的復(fù)用代價(jià)比釋放,創(chuàng)建新對(duì)象要小,這類(lèi)對(duì)象應(yīng)當(dāng)盡量放到一個(gè)緩存池里復(fù)用
對(duì)象調(diào)整
* CALayer:CALayer內(nèi)部并沒(méi)有屬性,當(dāng)調(diào)用屬性方法時(shí),它內(nèi)部是通過(guò)運(yùn)行時(shí)resolveInstanceMethod為對(duì)象臨時(shí)添加一個(gè)方法,并把對(duì)應(yīng)屬性值保存到內(nèi)部的一個(gè)Dictionary里,同時(shí)還會(huì)通知delegate,創(chuàng)建動(dòng)畫(huà)等等,非常消耗資源。
* UIView的關(guān)于顯示相關(guān)的屬性(frame/bound/transform)等實(shí)際上都是CALayer屬性映射來(lái)的,所以對(duì)UIView的這些屬性進(jìn)行調(diào)整時(shí),消耗的資源要遠(yuǎn)大于一般的屬性,所以,盡量減少不必要的屬性修改
* 當(dāng)視圖層次調(diào)整時(shí),UIView,CALayer之間會(huì)出現(xiàn)很多方法調(diào)用與通知,所以,應(yīng)盡量避免調(diào)整視圖層次,添加和移除視圖。
對(duì)象銷(xiāo)毀
把對(duì)象捕獲到block中,然后扔到后臺(tái)隊(duì)列去隨便發(fā)送個(gè)消息以避免編譯器警告,就可以讓對(duì)象在后臺(tái)線程銷(xiāo)毀了。
布局計(jì)算
* 視圖布局的計(jì)算是App中最為常見(jiàn)的消耗CPU資源的地方
* 在后臺(tái)線程提前計(jì)算好視圖布局,并且對(duì)視圖布局進(jìn)行緩存
* 用任何技術(shù)對(duì)視圖進(jìn)行布局,最終都會(huì)落到對(duì)UIView.frame/bounds/center等屬性的調(diào)整上 對(duì)象調(diào)整:非常消耗資源,所以盡量提前計(jì)算好布局,在需要時(shí)一次性調(diào)整好對(duì)應(yīng)屬性,而不要多次,頻繁的計(jì)算和調(diào)整這些屬性。
Autolayout
不手動(dòng)調(diào)整frame 等屬性,可以用常見(jiàn)的快捷屬性:left/right/top/bottom/width/height,或使用ComponentKit,AsyncDisplayKit等框架
文本渲染
* 所有的文本內(nèi)容控件,在底層都是通過(guò)CoreText排版,繪制為Bitmap顯示的。
* 常見(jiàn)的文本控件(UILabel,UITextView),其排版和繪制都是在主線程進(jìn)行的,當(dāng)顯示大量文本時(shí),CPU的壓力會(huì)非常大。
* 解決方案:自定義文本控件,用TextKit或底層的CoreText對(duì)文本異步繪制
* CoreText對(duì)象創(chuàng)建好后,能直接獲取文本的寬高信息,避免了多次計(jì)算(調(diào)整UILabel大小時(shí)算一遍,UILabel繪制時(shí)內(nèi)部再算一遍),CoreText對(duì)象占用內(nèi)存較少,可以緩存下來(lái)供稍后多次渲染。
圖片的解碼
* 用UIImage 或CGImageSource創(chuàng)建圖片時(shí),圖片數(shù)據(jù)不會(huì)立刻解碼。圖片設(shè)置到UIImageView或者CALayer.contents中去,并且CALayer被提交到GPU前,CGImage中的數(shù)據(jù)才會(huì)得到解碼。 _發(fā)生在主線程,不可避免。
* 后臺(tái)線程先把圖片會(huì)知道CGBitmapContext中,然后從Bitmap直接創(chuàng)建圖片。
圖像的繪制
* 圖像繪制:以CG開(kāi)頭的方法把圖像繪制到畫(huà)布中,然后從畫(huà)布創(chuàng)建圖片并顯示 如:[UIView drawRect:]
* CoreGraphic 方法通常是線程安全的,圖像的繪制可以放到后臺(tái)線程進(jìn)行
GPU 資源消耗原因和解決方案
GPU:接收提交的紋理和頂點(diǎn)描述(三角形),應(yīng)用變換(transform),混合并渲染,然后輸出到屏幕上。
所看到的內(nèi)容:紋理和形狀(三角形模擬的矢量圖形)
紋理的渲染
* 所有的Bitmap ,包括圖片,文本,柵格化的內(nèi)容,最終都要由內(nèi)存提交到顯存,綁定為GPU Texture.
* 提交到顯存的過(guò)程,GPU調(diào)整和渲染Texture的過(guò)程,都要消耗不少GPU資源
* 當(dāng)在較短時(shí)間顯示大量圖片(TableView存在非常多的圖片并且快速滑動(dòng)時(shí)),CPU占有率很低,GPU占有非常高,界面仍然會(huì)掉幀。
* 盡量減少在短時(shí)間內(nèi)大量圖片的顯示,盡可能將多張圖片合成為一張進(jìn)行顯示。
* 圖片過(guò)大,超過(guò)GPU的最大紋理尺寸時(shí),圖片需要先由CPU進(jìn)行預(yù)處理,這對(duì)CPU和GPU都會(huì)帶來(lái)額外的資源消耗。iPhone4S以上機(jī)型,紋理尺寸上限4096*4096
視圖的混合
* 當(dāng)多個(gè)視圖(CALayer)重疊在一起顯示時(shí),GPU會(huì)首先把他們混合到一起。如果視圖結(jié)構(gòu)過(guò)于復(fù)雜,混合的過(guò)程也會(huì)消耗很多GPU資源。
* 應(yīng)用應(yīng)當(dāng)盡量減少視圖數(shù)量和層次,并在不透明的視圖里標(biāo)明opaque屬性以避免無(wú)用的Alpha通道合成。
* 把多個(gè)視圖預(yù)先渲染為一張圖片來(lái)顯示。
圖形的生成
* CALayer的border,圓角,陰影,遮罩(mask),CASharpLayer的矢量圖形顯示,通常會(huì)觸發(fā)離屏渲染(offscreen rendering),而離屏渲染通暢發(fā)生在GPU中。
* 當(dāng)一個(gè)列表視圖中出現(xiàn)大量圓角的CALayer,并且快速滑動(dòng)時(shí),可以觀察到GPU資源已經(jīng)占滿,而CPU資源消耗很少。界面仍然能正?;瑒?dòng),但平均幀數(shù)會(huì)降到很低
* 避免這種情況,可以嘗試開(kāi)啟CALayer.shouldRasterize(柵格化)屬性,但這會(huì)把原本離屏渲染的操作轉(zhuǎn)嫁到CPU上去。
* 圓角圖片遮擋
* 把需要顯示的圖形在后臺(tái)線程繪制為圖片,避免使用圓角,陰影,遮罩等屬性。
-
cpu
+關(guān)注
關(guān)注
68文章
10863瀏覽量
211779
原文標(biāo)題:iOS構(gòu)建流暢的交互界面—CPU,GPU資源消耗的原因和解決方案
文章出處:【微信號(hào):Imgtec,微信公眾號(hào):Imagination Tech】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論