界面優(yōu)化

界面優(yōu)化

圖片顯示到屏幕上是CPU與GPU的協(xié)作完成

  • CPU: 計算視圖frame涣易,圖片解碼,需要繪制紋理圖片通過數(shù)據(jù)總線交給GPU
  • GPU: 紋理混合泥张,頂點變換與計算,像素點的填充計算详恼,渲染到幀緩沖區(qū)他嚷。
  • 時鐘信號:垂直同步信號V-Sync / 水平同步信號H-Sync默刚。
  • iOS設(shè)備雙緩沖機制:顯示系統(tǒng)通常會引入兩個幀緩沖區(qū)甥郑,雙緩沖機制


    image.png

二.圖片加載的工作流程

  1. 假設(shè)我們使用 +imageWithContentsOfFile: 方法從磁盤中加載一張圖片,這個時候的圖片并沒有解壓縮荤西;
  2. 然后將生成的 UIImage 賦值給 UIImageView
  3. 接著一個隱式的 CATransaction 捕獲到了 UIImageView 圖層樹的變化澜搅;
  4. 在主線程的下一個 runloop 到來時,Core Animation 提交了這個隱式的 transaction 邪锌,這個過程可能會對圖片進行 copy 操作勉躺,而受圖片是否字節(jié)對齊等因素的影響,這個 copy 操作可能會涉及以下部分或全部步驟:
  • 分配內(nèi)存緩沖區(qū)用于管理文件 IO 和解壓縮操作秃流;
  • 將文件數(shù)據(jù)從磁盤讀到內(nèi)存中赂蕴;
  • 將壓縮的圖片數(shù)據(jù)解碼成未壓縮的位圖形式柳弄,這是一個非常耗時的 CPU 操作舶胀;
  • 最后 Core Animation 中CALayer使用未壓縮的位圖數(shù)據(jù)渲染 UIImageView 的圖層。
  • CPU計算好圖片的Frame,對圖片解壓之后.就會交給GPU來做圖片渲染
  1. 渲染流程:
  • GPU獲取獲取圖片的坐標
  • 將坐標交給頂點著色器(頂點計算)
  • 將圖片光柵化(獲取圖片對應(yīng)屏幕上的像素點)
  • 片元著色器計算(計算每個像素點的最終顯示的顏色值)
  • 從幀緩存區(qū)中渲染到屏幕上
    我們提到了圖片的解壓縮是一個非常耗時的 CPU 操作碧注,并且它默認是在主線程中執(zhí)行的嚣伐。那么當(dāng)需要加載的圖片比較多時,就會對我們應(yīng)用的響應(yīng)性造成嚴重的影響萍丐,尤其是在快速滑動的列表上轩端,這個問題會表現(xiàn)得更加突出。
    卡頓監(jiān)控
    FPS監(jiān)控:為了保持流程的UI交互逝变,App的刷新拼搏應(yīng)該保持在60fps左右基茵,其原因是因為iOS設(shè)備默認的刷新頻率是60次/秒,而1次刷新(即VSync信號發(fā)出)的間隔是 1000ms/60 = 16.67ms壳影,所以如果在16.67ms內(nèi)沒有準備好下一幀數(shù)據(jù)拱层,就會產(chǎn)生卡頓

主線程卡頓監(jiān)控:通過子線程監(jiān)測主線程的RunLoop,判斷兩個狀態(tài)(kCFRunLoopBeforeSources 和 kCFRunLoopAfterWaiting)之間的耗時是否達到一定閾值

界面優(yōu)化
CPU層面的優(yōu)化
1宴咧、盡量用輕量級的對象代替重量級的對象根灯,可以對性能有所優(yōu)化,例如 不需要相應(yīng)觸摸事件的控件,用CALayer代替UIView
2烙肺、盡量減少對UIView和CALayer的屬性修改

  • CALayer內(nèi)部并沒有屬性纳猪,當(dāng)調(diào)用屬性方法時,其內(nèi)部是通過運行時resolveInstanceMethod為對象臨時添加一個方法桃笙,并將對應(yīng)屬性值保存在內(nèi)部的一個Dictionary中氏堤,同時還會通知delegate、創(chuàng)建動畫等怎栽,非常耗時
  • UIView相關(guān)的顯示屬性丽猬,例如frame、bounds熏瞄、transform等脚祟,實際上都是從CALayer映射來的,對其進行調(diào)整時强饮,消耗的資源比一般屬性要大
    3由桌、當(dāng)有大量對象釋放時,也是非常耗時的邮丰,盡量挪到后臺線程去釋放
    4行您、盡量提前計算視圖布局,即預(yù)排版剪廉,例如cell的行高
    5娃循、Autolayout在簡單頁面情況下們可以很好的提升開發(fā)效率,但是對于復(fù)雜視圖而言斗蒋,會產(chǎn)生嚴重的性能問題捌斧,隨著視圖數(shù)量的增長,Autolayout帶來的CPU消耗是呈指數(shù)上升的泉沾。所以盡量使用代碼布局捞蚂。如果不想手動調(diào)整frame等,也可以借助三方庫跷究,例如Masonry(OC)姓迅、SnapKit(Swift)、ComponentKit俊马、AsyncDisplayKit等
    6丁存、文本處理的優(yōu)化:當(dāng)一個界面有大量文本時,其行高的計算柴我、繪制也是非常耗時的
    1)如果對文本沒有特殊要求解寝,可以使用UILabel內(nèi)部的實現(xiàn)方式,且需要放到子線程中進行屯换,避免阻塞主線程
    計算文本寬高:[NSAttributedString boundingRectWithSize:options:context:]
    文本繪制:[NSAttributedString drawWithRect:options:context:]
    2)自定義文本控件编丘,利用TextKit 或最底層的 CoreText 對文本異步繪制与学。并且CoreText 對象創(chuàng)建好后,能直接獲取文本的寬高等信息嘉抓,避免了多次計算(調(diào)整和繪制都需要計算一次)索守。CoreText直接使用了CoreGraphics占用內(nèi)存小,效率高
    7抑片、圖片處理(解碼 + 繪制)
    1)當(dāng)使用UIImage 或 CGImageSource 的方法創(chuàng)建圖片時卵佛,圖片的數(shù)據(jù)不會立即解碼,而是在設(shè)置時解碼(即圖片設(shè)置到UIImageView/CALayer.contents中敞斋,然后在CALayer提交至GPU渲染前截汪,CGImage中的數(shù)據(jù)才進行解碼)。這一步是無可避免的植捎,且是發(fā)生在主線程中的衙解。想要繞開這個機制,常見的做法是在子線程中先將圖片繪制到CGBitmapContext焰枢,然后從Bitmap 直接創(chuàng)建圖片蚓峦,例如SDWebImage三方框架中對圖片編解碼的處理。這就是Image的預(yù)解碼
    當(dāng)使用CG開頭的方法繪制圖像到畫布中济锄,然后從畫布中創(chuàng)建圖片時暑椰,可以將圖像的繪制在子線程中進行
    8、圖片優(yōu)化
    1)盡量使用PNG圖片荐绝,不使用JPGE圖片
    2)通過子線程預(yù)解碼一汽,主線程渲染,即通過Bitmap創(chuàng)建圖片低滩,在子線程賦值image
    3)優(yōu)化圖片大小召夹,盡量避免動態(tài)縮放
    4)盡量將多張圖合為一張進行顯示
    9、盡量避免使用透明view委造,因為使用透明view戳鹅,會導(dǎo)致在GPU中計算像素時均驶,會將透明view下層圖層的像素也計算進來昏兆,即顏色混合處理,可以參考六妇穴、OpenGL 渲染技巧:深度測試爬虱、多邊形偏移、 混合這篇文章中提及的混合
    10腾它、按需加載跑筝,例如在TableView中滑動時不加載圖片,使用默認占位圖瞒滴,而是在滑動停止時加載
    11曲梗、少使用addView 給cell動態(tài)添加view
    GPU層面優(yōu)化
    1赞警、盡量減少在短時間內(nèi)大量圖片的顯示,盡可能將多張圖片合為一張顯示虏两,主要是因為當(dāng)有大量圖片進行顯示時愧旦,無論是CPU的計算還是GPU的渲染,都是非常耗時的定罢,很可能出現(xiàn)掉幀的情況
    2笤虫、盡量避免圖片的尺寸超過4096×4096,因為當(dāng)圖片超過這個尺寸時祖凫,會先由CPU進行預(yù)處理琼蚯,然后再提交給GPU處理,導(dǎo)致額外CPU資源消耗
    3惠况、盡量減少視圖數(shù)量和層次遭庶,主要是因為視圖過多且重疊時,GPU會將其混合稠屠,混合的過程也是非常耗時的
    4罚拟、盡量避免離屏渲染,可以查看這篇文章四完箩、深入剖析【離屏渲染】原理
    5赐俗、異步渲染,例如可以將cell中的所有控件弊知、視圖合成一張圖片進行顯示阻逮。可以參考Graver三方框架
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(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
  • 正文 為了忘掉前任舔稀,我火速辦了婚禮,結(jié)果婚禮上掌测,老公的妹妹穿的比我還像新娘内贮。我一直安慰自己,他們只是感情好汞斧,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布夜郁。 她就那樣靜靜地躺著,像睡著了一般粘勒。 火紅的嫁衣襯著肌膚如雪竞端。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天庙睡,我揣著相機與錄音事富,去河邊找鬼。 笑死乘陪,一個胖子當(dāng)著我的面吹牛统台,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播啡邑,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼贱勃,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了谤逼?” 一聲冷哼從身側(cè)響起贵扰,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎流部,沒想到半個月后戚绕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡枝冀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年舞丛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宾茂。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡瓷马,死狀恐怖拴还,靈堂內(nèi)的尸體忽然破棺而出跨晴,到底是詐尸還是另有隱情,我是刑警寧澤片林,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布端盆,位于F島的核電站怀骤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏焕妙。R本人自食惡果不足惜蒋伦,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望焚鹊。 院中可真熱鬧痕届,春花似錦、人聲如沸末患。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽璧针。三九已至嚷炉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間探橱,已是汗流浹背申屹。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留隧膏,地道東北人哗讥。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像胞枕,于是被迫代替她去往敵國和親忌栅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

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