001性能優(yōu)化-02-界面優(yōu)化.md

[TOC]

基礎優(yōu)化方向

  1. 使用 ARC 管理內(nèi)存

  2. 在正確的地方使用 reuseIdentifier

    • tableview 用 tableView:cellForRowAtIndexPath: 為 rows 分配 cells 的時候眶俩,他的數(shù)據(jù)應該重用自 UITableViewCell
  3. 盡量將 views 設置為不透明(Opaque)

  4. 避免過于龐大的 XIB

  5. 不要阻塞主線程

    • 用于不要是主線程承擔過多。因為UIKit在主線程上做所有工作谷市,

    • 渲染亿蒸、管理觸摸反應、回應輸入等都需要在主線程上完成

    • 大部分阻礙主線程的情形是你的APP在做一些涉及到讀寫外部資源的 I/O 操作沧竟,比如存儲或者網(wǎng)絡:

      image
  1. 不要在 viewWillAppear 中做費時的操作

    • viewWillAppear前翎,在 view 顯示之前被調(diào)用杆融,處于效率考慮燃乍,方法中不要處理復雜費時操作唆樊。
    • 只能在該方法中設置 view 的顯示屬性之類的簡單事情,例如背景色刻蟹、字體等逗旁。否則,會明顯感覺到 view 有卡頓或者延遲舆瘪。

圖片處理

  1. 在 ImageView 中調(diào)整圖片大小片效。

  2. 保證圖片大小和 UIImageView 大小相同。

    如果要在 UIIImageView 中顯示一個來自 bundle 的圖片英古,你應保證圖片的大小和 UIImageView 大小相同淀衣。

  3. 在運行中縮放圖片是耗費資源的,特別是 UIImageView 嵌套在 UIScrollView 中的情況下哺呜。

  4. 處理網(wǎng)絡圖片舌缤。如果圖片是從遠端服務器加載的,你無法控制圖片大小某残。那么就在下載完成之后国撵,最好是在 background thread中,縮放一次玻墅,然后在 UIImageView 中使用縮放之后的圖片介牙。

  • imageNamed 初始化:加載圖片、并緩存

    • imageNamed 默認加載圖片成功后澳厢,內(nèi)存中會緩存圖片环础。
    • 這個方法用一個指定的名字在系統(tǒng)緩存中查找并返回一個圖片對象。
    • 如果緩存中沒有找到響應的圖片對象剩拢,則從指定地方加載圖片线得,然后緩存對象,并返回這個而圖片對象徐伐。
  • imageWithContentsOfFile 初始化

    • imageWithContentOfFile 則僅只加載贯钩、不緩存。
    • 如果加載一張大圖并且使用一次办素,用 imageWithContentsOfFile 是最好的角雷,這樣 CPU 不需要做緩存,可以節(jié)約時間性穿。
  • 具體使用哪一種需要根據(jù)應用場景加以區(qū)分勺三,UIImage 雖小,但是是使用非常多的元素需曾,也會有比較顯著的問題吗坚。

    • “不以善小而不為,不以惡小而為之”
    • “不積跬步無以至千里”
  • UIImageView

    • 在性能的范圍之內(nèi)胯舷,直接對 UIImageView 設置圓角是不會觸發(fā)離屏渲染的刻蚯,但同時給 UIImageView 設置背景色肯定會觸發(fā)離屏渲染
    • 觸發(fā)離屏渲染跟 .png.jpg 格式無關

UITableView 優(yōu)化

view相關操作

  • 正確使用 reuseIdentifier 來重用 cells
  • 減少subview的數(shù)量
  • 盡量使所有的 view opaque(不透明),包括cell自身
  • 使用 shadowPath 來畫陰影
  • 避免漸變桑嘶、圖片縮放

緩存相關操作

  • 緩存行高
  • 盡量不要使用 cellForRowAtIndexPath炊汹。如果要使用,只用一次逃顶,然后緩存結果
  • 盡量使用 rowHeight讨便、sectionHeight、sectionHeaderHeight 來設定固定的行高以政,不要請求delegate

數(shù)據(jù)加載相關操作

  • 如果 cell 內(nèi)實現(xiàn)的內(nèi)容來自 web霸褒,使用異步加載,緩存請求結果
  • 使用正確的數(shù)據(jù)結果來存儲數(shù)據(jù)

CPU 和 GPU 層優(yōu)化

本質上是降低 CPU盈蛮、GPU的工作废菱,從這兩個方面入手去提升性能

  • CPU做了什么事

    • 邏輯運算
    • 對象的創(chuàng)建
    • 對象屬性的調(diào)整、布局計算、文本的計算和排版
    • 圖片的格式轉碼和解碼
    • 圖像的繪制
  • GPU做了什么事

    • 數(shù)學運算
    • 紋理繪制

CPU 層面的優(yōu)化

  • 盡量用輕量級的對象殊轴,比如用不到時間處理的地方衰倦,可以考慮使用 CALayer 取代 UIView
  • 不要頻繁調(diào)用 UIView 的相關屬性,例如 frame旁理、bounds樊零、transform 等屬性,盡量減少不必要的修改
  • 盡量提前計算好布局孽文,在有需要時一次性調(diào)整對應的屬性驻襟,不要對此修改屬性
  • Autolayout 會比直接設置 frame 消耗更多的 CPU 資源
  • 圖片的 size 最好剛好更 UIImageView 的 size 保持一致
  • 控制一下 線程的最大并發(fā)數(shù)量
  • 盡量把耗時操作放到子線程
    • 文本處理(尺寸計算、繪制)
    • 圖片處理(解碼芋哭、繪制)

GPU 層面的優(yōu)化

  • 盡量避免短時間內(nèi)大量圖片的顯示沉衣,盡可能你將多張圖片合成一張進行顯示
  • GPU 能處理的最大紋理尺寸是 4096x4096,一旦超過這個尺寸减牺,就會占用 CPU 資源進行處理厢蒜,所以紋理盡量不要超過這個尺寸
  • 盡量減少視圖數(shù)據(jù)和層次
  • 減少透明的視圖(alpha<1),不透明的就設置 opaque 為 YES(打開繪制優(yōu)化開關)
  • 盡量避免出現(xiàn)離屏渲染

離屏渲染優(yōu)化

如何高性能的畫一個圓角烹植?

視圖和圓角的大小對幀率并沒有什么影響斑鸦,數(shù)量最核心的影響因素

image

這個是我們最常規(guī)的設置方式,但不可取草雕,因為會觸發(fā)離屏渲染

  • 如果能夠只用 cornerRadius 解決問題巷屿,就不用優(yōu)化
  • 如果必須設置 maskToBounds,可以參考圓角視圖的數(shù)量墩虹,如果數(shù)量少(一頁只有幾個)也可以考慮不用優(yōu)化嘱巾。
  • UIImageView 的圓角通過直接截取圖片實現(xiàn),其他視圖的圓角可以通過 Core Graphics 畫出圓角矩陣實現(xiàn)
  • 通過 CoreGraphic 畫一個圓角诫钓,不會觸發(fā)離屏渲染
image

什么是 “離屏渲染”旬昭?

離屏渲染就是在當前屏幕緩沖區(qū)外,新開辟一個緩沖區(qū)進行操作菌湃。

  • 在 OpenGL 中问拘,GPU 有2中渲染方式

    • On-Screen Rendering:當前屏幕渲染,在當前用于顯示的屏幕緩沖區(qū)進行渲染操作
    • Off-Screen Rendering:離屏渲染惧所,在當前屏幕緩沖區(qū)以外開辟一個緩沖區(qū)進行渲染操作

為何要避免離屏渲染骤坐?

CPU、GPU 在繪制渲染視圖是做了大量的工作下愈。離屏渲染發(fā)生在 GPU 層面上纽绍,會創(chuàng)建新的渲染緩緩沖區(qū),會觸發(fā) OpenGL 的多通道渲染管線势似,圖像上下文切換會早晨額外的開銷拌夏,增加 GPU 工作量僧著。如果CPU、GPU累計耗時 16.67 ms還沒有完成障簿,就會造成卡頓掉幀霹抛。

圓角屬性、蒙層遮罩 都會觸發(fā)離屏渲染卷谈。指定以上屬性,標記了它在新的圖形上下文中霞篡,在未愈合之前世蔗,不可以用于顯示的時候就觸發(fā)了離屏渲染。

離屏渲染消耗性能的原因朗兵?

  • 需要創(chuàng)建新的緩沖區(qū)

  • 離屏渲染的整個過程污淋,需要多次切換上下文環(huán)境

    • 上下文先從當前屏幕(On-Screen)切換到離屏(Off-Screen)
    • 等離屏渲染結束后,將離屏緩沖區(qū)的結果顯示到屏幕上
    • 再將上下文切換到當前屏幕

哪些操作會觸發(fā)離屏渲染余掖?

  1. layer.shouldRasterzize:光柵化

    • 光柵化概念:將圖轉化為一個個柵格組成的圖像
    • 光柵化特點:每個元素對應幀緩沖區(qū)的一像素
    • 光柵化限制:系統(tǒng)給光柵化限制了內(nèi)存寸爆,如果超過就會觸發(fā)離屏渲染,所以cell中一般不使用
  2. mask:遮罩

  3. shadows:layer.shadowXXX盐欺,如果設置了 layer.shadowPath 就不會產(chǎn)生離屏渲染

  4. group opacity:不透明赁豆,layer屬性

  5. edge antialiasing:抗鋸齒

  6. cornerRadius:圓角。同時設置 layer.masksToBounds = YES; layer.cornerRadius 大于0冗美,考慮通過 CoreGraphics 繪制圓角魔种,或者讓美工提供圓角圖片

  7. 漸變

  8. drawRect

離屏渲染 VS CPU 渲染

上面說到了,所有不在 GPU 的當前屏幕緩沖區(qū)進行的渲染都叫離屏渲染粉洼,還有另外一種特殊的離屏渲染节预,叫“CPU 渲染”。

  • CPU渲染:

    • 如果重寫了 drawRect 方法属韧,并且使用任何 Core Graphics 的技術安拟,進行了繪制操作,就涉及到了 CPU渲染
    • 整個渲染過程由 CPU 在 APP 內(nèi)同步完成宵喂,渲染得到的 bitmap 最后交給 GPU 用于顯示

由于 GPU 的浮點運算能力比 CPU 強糠赦,CPU 渲染的效率可能不如離屏渲染。但如果只是實現(xiàn)一個簡單的效果锅棕,直接使用CPU渲染就可以愉棱,因為離屏渲染涉及到緩沖區(qū)創(chuàng)建以及上下文切換等耗時操作。

如何檢測離屏渲染哲戚?

  1. 模擬器:Debug->Color Off-screen Rendered

    image
    image
    image

    可以看到圖片亮黃色部分就是離屏渲染的視圖

  2. 真機:xcode9之后可以不用 Instrument 了奔滑,運行程序之后:Debug -> View Debugging -> Rendering -> Color Offscreen-Rendered Yellow

    設置路徑
    image

離屏渲染的解決思路

  1. 預排班,提前計算

    在接收到服務器端返回的數(shù)據(jù)后顺少,盡量將 CoreText 排版的結果朋其、單個空間的高度王浴、cell 整體的高度提前計算好,將其存儲在模型的屬性中梅猿。需要使用時氓辣,知己耳聰模型中往外取,避免了計算的過程袱蚓。

    盡量少用 UILabel钞啸,可以使用 CALayer。避免使用 AutoLayout 的自動布局喇潘,才去純代碼的方式

  2. 預渲染体斩,提前繪制

    圓形的圖標可以提前在:接收到網(wǎng)絡返回數(shù)據(jù)時,后臺線程進行處理颖低,直接存儲在模型數(shù)據(jù)中絮吵,回到主線程后直接調(diào)用

    避免使用 CALayer 的 Border、Corner忱屑、Shadow蹬敲、Mask 等技術,這些都會觸發(fā)離屏渲染

  3. 異步繪制

  4. 全局并發(fā)線程

  5. 高效的圖片異步加載

圖層混合優(yōu)化

  1. 怎么檢測圖層混合

    在下面 instrument 工具介紹中有給出

  2. 怎么避免圖層混合

    • 確陛航洌控件的 Opaque 屬性設置為 true
    • 確卑槲耍控件的 背景色 和父視圖的背景色一致 且不透明
    • 如無特殊需要,不要設置低于 1 的 alpha 值
    • 確保 UIImage 沒有alpha 通道
    • UILabel iOS8以后設置背景色為非透明 和 設置 label.layer.masksToBounds=YES从铲,就可以讓label只渲染給定的size區(qū)域闹究,解決 UILabel 的圖層混合問題

instrument 工具

上面講到了如何檢測離屏渲染,除了離屏渲染 Rendering 還有其他幾種調(diào)試類型

  • Color Blended Layer :圖層混合

    表示區(qū)域使用多種混合圖層食店,(圖層混合:由于多 UI/Layer 疊加渣淤,如果有透明或半透明顏色時,CPU就會去計算最終顯示的顏色吉嫩,中間就涉及很很多多余計算价认。

    顏色標識

      - 紅色:混合圖層
      - 綠色:沒有使用混合
    

    調(diào)優(yōu)

      減少紅色區(qū)域
      
      1. 設置 Opaque 屬性為 YES
      2. 給 view 設置一個不透明的顏色
    
    image

    image
  • Color Hits green and Misses Red:光柵化(緩存layer)

    檢測 layer 是否使用 shouldRasterize,為true開啟光柵化(默認)自娩,光柵化會將layer預先渲染為位圖 bitmap用踩,然后緩存,從而提高性能忙迁。

    顏色標識

      - 紅色:光柵化
      - 綠色:未光柵化
    

    調(diào)優(yōu)

      使用內(nèi)容不變的layer脐彩,不適合tableview,會造成多余離屏渲染降低性能(原因:系統(tǒng)給光柵化限制了內(nèi)存姊扔,如果超過就會離屏渲染)
    
    image
  • Color copied Images 圖片格式檢測與復制

    Shows images that are copied by Core Animation in blue惠奸,蘋果官方注釋說 被拷貝給CPU進行轉化的圖片顯示為綠色。

    如果 GPU 不支持當前圖片的顏色格式恰梢,那么就會將圖片交給 CPU 預先進行格式轉化佛南,并且這張圖片標記為綠色梗掰。

    GPU 只解析 32 bit 的顏色格式,如果使用 Color Copied Images 調(diào)試嗅回,圖片是藍色

    顏色標識

      - 藍色:需要賦值
    

    擴展

       32bit 指圖片顏色深度及穗,用“位”來表示,用來表示顯示顏色數(shù)量绵载,例如一個圖片支持256種顏色埂陆,那么就需要256個不同的值來表示不同的顏色,就需要0-255娃豹,二進制表示就是從 00000000-11111111焚虱,一共需要 8位 二進制數(shù),所以**顏色深度是 8**培愁。通常32bit色彩中使用3個bit表示R(紅)G(綠)B(藍),還有一個 8bit 表示 Alpha(透明度)
    
  • Color misaliged Images:圖片尺寸匹配

    目標像素與源像素不對齊的圖片缓窜,比如圖片大小和 UIImageView 大小不一致

    顏色標識

      - 洋紅色:圖片沒有像素對齊
      - 黃色:圖片縮放
    

    優(yōu)化

      盡量匹配大小
    
  • Color Compositing Fast-Path Blue:快速路徑

    標記由硬件繪制的路徑定续,顯示藍色,越多越好禾锤∷焦桑可以直接對OpenGL繪制的圖像高亮。

    顏色標識

      - 藍色
    

    優(yōu)化

      一般不做檢測
    
  • Flash updated Regions:重繪區(qū)域

    對重繪區(qū)域高亮為黃色恩掷,會使用 CoreGraphic 繪制倡鲸,越小越好

    顏色標識

      - 黃色
    
  • Color Immediately:顏色刷新頻率

    當執(zhí)行顏色刷新的時候移除 10ms 的延遲,因為可能在特定情況下你不需要這些延遲黄娘,所以使用此選項加快顏色刷新的頻率峭状。

    一般用不到

opaque 繪制優(yōu)化

這個值不是決定視圖是否是透明的,而是給繪制系統(tǒng)提供一個個性能優(yōu)化的開關

  • YES:不透明逼争。UIView 默認為 YES
  • NO:透明优床。UIButton、UILabel等子類默認為 NO

red + green = yellow

image

在第一篇文章中介紹了一個公式:

R = S + D * (1 - Sa)

- R:像素RGB
- S:源色彩(頂端紋理)
- D:目標顏色(低一層的紋理)
- Sa:源色彩的透明度
  • redView = (1, 0, 0, 1)
  • greenView = (0, 1, 0, 0.5)

R = 1 + 0 * (1-0.5)
G = 0 + 1 * (1-0.5)
B = 0 + 0 * (1-0.5)
A = 1 + 0.5 * (1-0.5)

  • 得出結果是:(1, 0.5, 0, 1)

而當 Sa=1 時誓焦,R=S胆敞,也就是說。這個時候不管目標顏色是什么杂伟,GPU 都不需要做任何計算合成移层。只需要簡單的從這個層進行拷貝,節(jié)省了GPU大量的工作量赫粥。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末观话,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子越平,更是在濱河造成了極大的恐慌匪燕,老刑警劉巖蕾羊,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異帽驯,居然都是意外死亡龟再,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門尼变,熙熙樓的掌柜王于貴愁眉苦臉地迎上來利凑,“玉大人,你說我怎么就攤上這事嫌术“С海” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵度气,是天一觀的道長割按。 經(jīng)常有香客問我,道長磷籍,這世上最難降的妖魔是什么适荣? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮院领,結果婚禮上弛矛,老公的妹妹穿的比我還像新娘。我一直安慰自己比然,他們只是感情好丈氓,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著强法,像睡著了一般万俗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上饮怯,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天该编,我揣著相機與錄音,去河邊找鬼硕淑。 笑死课竣,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的置媳。 我是一名探鬼主播于樟,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼拇囊!你這毒婦竟也來了迂曲?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤寥袭,失蹤者是張志新(化名)和其女友劉穎路捧,沒想到半個月后关霸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡杰扫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年队寇,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片章姓。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡佳遣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出凡伊,到底是詐尸還是另有隱情零渐,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布系忙,位于F島的核電站诵盼,受9級特大地震影響,放射性物質發(fā)生泄漏银还。R本人自食惡果不足惜风宁,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望见剩。 院中可真熱鬧杀糯,春花似錦扫俺、人聲如沸苍苞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽羹呵。三九已至,卻和暖如春疗琉,著一層夾襖步出監(jiān)牢的瞬間冈欢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工盈简, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留凑耻,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓柠贤,卻偏偏與公主長得像香浩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子臼勉,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344