iOS開發系列之性能優化(上)

本篇主要記錄一下我對界面優化上的一些探索。關於時間優化的探索將會在中篇裏進行介紹。下篇將主要介紹一些耗電優化、安裝包瘦身的探索。php

一、卡頓原理

要了解卡頓原理,須要對幀緩衝區、垂直同步、CPU 和 GPU 幾個詞進行一下了解,而後綜合起來,就能夠獲得卡頓的答案。本篇我就按照本身的理解來進行描述,若有不當,歡迎指正。ios

1.一、幀緩衝區

聽起來很高大上,其實就是用來存放每一幀畫面數據的一個「倉庫」,一個倉庫只存放一幀畫面的數據,iOS 一直是雙緩存,就是有兩個倉庫,存當前幀數據的叫「正式倉庫」,存下一幀數據的叫「預備倉庫」。git

當正式倉庫的數據被取走後,二者身份交換,原來的預備倉庫轉正爲正式倉庫,原來的正式倉庫變成預備倉庫。github

1.二、垂直同步 (VSync)

就是一個「信號」,通知 app 該開始準備往預備倉庫裏存放數據了,系統過一會就要來取,這個時間大概是16毫秒。緩存

1.三、CPU (中央處理器)

主要的工做有:正式對象的建立和銷燬、對象屬性的調整、佈局計算、文本的計算和排版、圖片的格式轉換和解碼、圖像的繪製。咱們能夠理解爲負責包裹內部的處理工做,簡稱「打包」。性能優化

1.四、GPU (圖形處理器)

主要的工做有:將 CPU 計算好的內容進行變換、合成、渲染等處理,而後將渲染結果提交到幀緩衝區。咱們能夠理解爲,對 CPU 給過來的包裹進行分類、排列等操做後,存放到倉庫裏去,簡稱「入庫」。app

1.五、卡頓原理

當收到系統發過來的 VSync 「信號」後,CPU 就開始對這一幀畫面的數據進行「打包」,而後交給 GPU 進行「入庫」操做,存入到「預備倉庫」中。框架

16毫秒後,預備倉庫轉正,系統開始讀取倉庫裏的數據,若是這個時候,倉庫中的數據尚未準備好,那麼系統就會發脾氣,放棄讀取倉庫中的數據。異步

那麼這個時候,由於系統的寧缺毋濫,致使了顯示器上顯示的仍是上一幀畫面,就形成了卡頓的效果。佈局

二、性能優化

做爲軟件開發工程師的咱們,既不能延長16毫秒的處理時間,也不能改變系統的脾氣,那咱們能作的就是儘可能在這個時間內完成數據的準備。要麼「打包」快一點,要麼「入庫」快一點,也就是針對 CPU 和 GPU 的工做進行優化,這就是性能優化的工做了。

2.一、CPU 工做之正式對象的建立和銷燬

  • UITableViewCell 和 UICollectionViewCell 的複用,能夠減小 cell 的建立操做;

  • 儘可能使用輕量級的對象,能夠減小對象的建立時間,好比在不須要事件處理的場景裏,使用CALayer 比 UIView 會更加合適;

  • 表情鍵盤使用 UICollectionViewCell 代替 UIButton,能夠減小對象的建立操做;

  • 對象不涉及UI操做,放到後臺線程建立;

  • 性能要求嚴格的界面,storyborad的資源消耗>代碼建立;

  • 推遲對象建立的時間,對象放到多個任務中,好比懶加載;

2.二、CPU 工做之對象屬性的調整

  • UIView 有一個 CALyer 的屬性,UIView 負責事件的處理,CALyer 負責圖層的繪製和顯示。須要注意的是,CALyer自己是沒有屬性的,因此當改變 UIView 的顯示相關的屬性如 frame、bounds 和 transform 的時候,會消耗較多的資源,因此減小對這些屬性的一些沒必要要修改,能減少 CPU 的壓力;

2.三、CPU 工做之佈局計算

  • UITableViewCell 高度提早計算並存儲,要用的時候直接讀取;

  • frame 計算好,較少沒必要要的修改;

  • Autolayout會比直接設置frame消耗更多的CPU資源;

2.四、CPU 工做之文本的計算和排版

  • 普通文本能夠在子線程用 [NSAttributedString boundingRectWithSize:options:context:] 來計算文本寬高,用 -[NSAttributedString drawWithRect:options:context:] 來繪製文本;

  • CoreText 對象佔用內存較少,當顯示大量文本時,能夠用 CoreText 對文本異步繪製;

2.五、CPU 工做之圖片的格式轉換和解碼

  • 在後臺線程先把圖片繪製到 CGBitmapContext 中,而後從 Bitmap 直接建立圖片;

2.六、CPU 工做之圖像的繪製

  • UITableViewCell 滑動減速的時候才加載圖片,能夠參考這個demo

  • 加載圖片時,imageNamed 方法默認加載圖片成功後會內存中緩存圖片,下次讀取會很快;imageWithContentsOfFile 方法不會緩存圖片,大圖片可使用該方法;

2.七、GPU 工做之渲染

  • 儘可能不要讓圖片和視圖的大小超過 GPU 紋理尺寸上限:4096×4096,否則圖片還須要通過 CPU 的處理;

  • 儘可能減小視圖數量和層次,並設置視圖爲不透明,UIView 的不透明屬性 (opaque) 默認爲 YES,通常設置背景顏色便可;CALayer 的不透明屬性 (opaque) 默認爲 NO,須要設置爲 YES;

  • CALayer 的 border、圓角、陰影、遮罩,一般會觸發離屏渲染,儘可能少用,圓角屬性可使用 CoreGraphics 繪製或使用圓角圖片代替,關於離屏渲染的知識,具體能夠參考這篇文章:iOS 圖形性能優化;

  • 圖片的 size 最好恰好跟 UIImageView 的 size 保持一致,這涉及到像素對齊的知識,也能夠在上面這篇文章中詳細瞭解;

最後鄭重聲明,本篇裏只是記錄一下個人我的理解和代碼實踐,資料大量參考了這篇文章:iOS 保持界面流暢的技巧,做者是寫出了 YYKit 框架的大牛,想要深刻學習的朋友請移步。

本篇的界面優化就記錄到這裏,後面會持續更新,歡迎指正。

相關文章
相關標籤/搜索