歡迎光臨
每天分享高質量文章

iOS效能最佳化篇

來自:slimsallen

連結:https://juejin.im/post/5b7a9c466fb9a019eb43b0d5


好的app應該有好的效能流暢度,本篇文章就大概講一下ios效能最佳化。

先來談談CPU和GPU

在螢幕成像的過程中,CPU和GPU起著至關重要的作用

CPU( Central Processing Unit, 中央處理器)就是機器的“大腦”,也是佈局謀略、發號施令、控制行動的“總司令官”。

CPU的結構主要包括運算器(ALU, Arithmetic and Logic Unit)、控制單元(CU, Control Unit)、暫存器(Register)、高速快取器(Cache)和它們之間通 訊的資料、控制及狀態的匯流排。

GPU全稱為Graphics Processing Unit,中文為圖形處理器,就如它的名字一樣,GPU最初是用在個人電腦、工作站、遊戲機和一些移動裝置(如平板電腦、智慧手機等)上執行繪圖運算工作的微處理器。

為什麼GPU特別擅長處理影象資料呢?這是因為影象上的每一個畫素點都有被處理的需要,而且每個畫素點處理的過程和方式都十分相似,也就成了GPU的天然溫床。

在iOS中是雙緩衝機制,有前幀快取、後幀快取,即GPU會預先渲染好一幀放入一個緩衝區內(前幀快取),讓影片控制器讀取,當下一幀渲染好後,GPU會直接把影片控制器的指標指向第二個緩衝器(後幀快取)。當你影片控制器已經讀完一幀,準備讀下一幀的時候,GPU會等待顯示器的VSync訊號發出後,前幀快取和後幀快取會瞬間切換,後幀快取會變成新的前幀快取,同時舊的前幀快取會變成新的後幀快取。

螢幕成像原理

卡頓產生的原因

在Sync訊號到來後,系統圖形服務會透過CADisplayLink等機制通知App,App主執行緒開始在CPU中計算顯示內容,比如檢視的建立,佈局計算,圖片解碼,文字繪製等。隨後CPU會將計算好的內容提交到GPU去,由GPU進行交換,合成,渲染。隨後GPU會把渲染結果提交到幀緩衝區,等待下一次VSync訊號(垂直同步訊號)到來時顯示到螢幕上。由於垂直同步機制,如果在一個VSync時間內,CPU或者GPU沒有完成內容提交,則那一幀就會被丟棄,等待下一次機會再顯示,而這時顯示屏因為沒有新的掃清,會保留之前的內容不變。這就造成了卡頓。

  • 按照60FPS的刷幀率,每隔16ms就會有一次VSync訊號

卡頓最佳化 -CPU

  • 儘量用輕量級的物件,比如用不到事件處理的地方,可以考慮使用CALayer取代UIView

  • 不要頻繁地呼叫UIView的相關屬性,比如frame、bounds、transform等屬性,儘量減少不必要的修改

  • 儘量提前計算好佈局,在有需要時一次性調整對應的屬性,不要多次修改屬性

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

  • 圖片的size最好剛好跟UIImageView的size保持一致

  • 控制一下執行緒的最大併發數量

  • 儘量把耗時的操作放到子執行緒

卡頓最佳化 -GPU

  • 儘量避免短時間內大量圖片的顯示,盡可能將多張圖片合成一張進行顯示

  • 儘量減少檢視數量和層次

  • 減少透明的檢視(alpha<1),不透明的就設定opaque為YES

  • 儘量避免出現離屏渲染

離屏渲染

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

1、On-Screen Rendering:當前螢幕渲染,在當前用於顯示的螢幕緩衝區進行渲染操作

2、Off-Screen Rendering:離屏渲染,在當前螢幕緩衝區以外新開闢一個緩衝區進行渲染操作

  • 離屏渲染消耗效能的原因

1、需要建立新的緩衝區

2、離屏渲染的整個過程,需要多次切換背景關係環境,先是從當前螢幕(On-Screen)切換到離屏(Off-Screen);等到離屏渲染結束以後,將離屏緩衝區的渲染結果顯示到螢幕上,又需要將背景關係環境從離屏切換到當前螢幕

  • 哪些操作會觸發離屏渲染?

1、光柵化,layer.shouldRasterize = YES

2、遮罩,layer.mask

3、圓角,同時設定layer.masksToBounds = YES、layer.cornerRadius大於0。考慮透過CoreGraphics繪製裁剪圓角,或者叫美工提供圓角圖片

4、陰影,layer.shadowXXX。如果設定了layer.shadowPath就不會產生離屏渲染

耗電最佳化


耗電的主要來源?


  • CPU處理,Processing

  • 網路,Networking

  • 定位,Location

  • 影象,Graphics

定位最佳化

  • 如果只是需要快速確定使用者位置,最好用CLLocationManager的requestLocation方法。定位完成後,會自動讓定位硬體斷電

  • 如果不是導航應用,儘量不要實時更新位置,定位完畢就關掉定位服務

  • 儘量降低定位精度,比如儘量不要使用精度最高的kCLLocationAccuracyBest

  • 需要後臺定位時,儘量設定pausesLocationUpdatesAutomatically為YES,如果使用者不太可能移動的時候系統會自動暫停位置更新

  • 儘量不要使用startMonitoringSignificantLocationChanges,優先考慮startMonitoringForRegion:

APP啟動最佳化


先來看app啟動流程

APP的啟動可以分為2種

1、冷啟動(Cold Launch):從零開始啟動APP

2、熱啟動(Warm Launch):APP已經在記憶體中,在後臺存活著,再次點選圖示啟動APP

APP啟動時間的最佳化,主要是針對冷啟動進行最佳化

  • 透過新增環境變數可以打印出APP的啟動時間分析(Edit scheme -> Run -> Arguments)

1、DYLD_PRINT_STATISTICS設定為1

2、如果需要更詳細的資訊,那就將DYLD_PRINT_STATISTICS_DETAILS設定為1

APP的冷啟動概括為三大階段

  • dyld,Apple的動態聯結器,可以用來裝載Mach-O檔案(可執行檔案、動態庫等)

    啟動APP時,dyld所做的事情有

    1、裝載APP的可執行檔案,同時會遞迴載入所有依賴的動態庫

    2、當dyld把可執行檔案、動態庫都裝載完畢後,會通知Runtime進行下一步的處理

    • runtime

      啟動APP時,runtime所做的事情有

      1、呼叫map_images進行可執行檔案內容的解析和處理

      2、在load_images中呼叫call_load_methods,呼叫所有Class和Category的+load方法

      3、進行各種objc結構的初始化(註冊Objc類 、初始化類物件等等)

      4、呼叫C++靜態初始化器和__attribute__((constructor))修飾的函式

      到此為止,可執行檔案和動態庫中所有的符號(Class,Protocol,Selector,IMP,…)都已經按格式成功載入到記憶體中,被runtime 所管理

      • main

        1、APP的啟動由dyld主導,將可執行檔案載入到記憶體,順便載入所有依賴的動態庫

        2、並由runtime負責載入成objc定義的結構

        3、所有初始化工作結束後,dyld就會呼叫main函式

        4、接下來就是UIApplicationMain函式,AppDelegate的application:didFinishLaunchingWithOptions:方法

        最佳化方案

        一、dyld

        • 減少動態庫、合併一些動態庫(定期清理不必要的動態庫)

        • 減少Objc類、分類的數量、減少Selector數量(定期清理不必要的類、分類)

        • 減少C++虛函式數量

        • Swift儘量使用struct

        二、runtime

        用+initialize方法和dispatch_once取代所有的__attribute__((constructor))、C++靜態建構式、ObjC的+load

        三、main

        • 在不影響使用者體驗的前提下,盡可能將一些操作延遲,不要全部都放在finishLaunching方法中

        • 按需載入

        後面會分享自己的最佳化過程

        Follow:https://github.com/sallenhandong

        Source:https://slimsallen.com/#/detail/iosperformance.md


        編號287,輸入編號直達本文

        ●輸入m獲取文章目錄

        推薦↓↓↓

        Web開發

        更多推薦18個技術類微信公眾號

        涵蓋:程式人生、演演算法與資料結構、駭客技術與網路安全、大資料技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。

贊(0)

分享創造快樂