IOS性能優化篇

好的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

1. 定位優化

  • 若是隻是須要快速肯定用戶位置,最好用CLLocationManager的requestLocation方法。定位完成後,會自動讓定位硬件斷電
  • 若是不是導航應用,儘可能不要實時更新位置,定位完畢就關掉定位服務
  • 儘可能下降定位精度,好比儘可能不要使用精度最高的kCLLocationAccuracyBest
  • 須要後臺定位時,儘可能設置pausesLocationUpdatesAutomatically爲YES,若是用戶不太可能移動的時候系統會自動暫停位置更新
  • 儘可能不要使用startMonitoringSignificantLocationChanges,優先考慮startMonitoringForRegion:

APP啓動優化

先來看app啓動流程

APP的啓動能夠分爲2種

一、冷啓動(Cold Launch):從零開始啓動APP
二、熱啓動(Warm Launch):APP已經在內存中,在後臺存活着,再次點擊圖標啓動APPios

APP啓動時間的優化,主要是針對冷啓動進行優化

  • 經過添加環境變量能夠打印出APP的啓動時間分析(Edit scheme -> Run -> Arguments)
    一、DYLD_PRINT_STATISTICS設置爲1
    二、若是須要更詳細的信息,那就將DYLD_PRINT_STATISTICS_DETAILS設置爲1

APP的冷啓動歸納爲三大階段

  • dyld,Apple的動態連接器,能夠用來裝載Mach-O文件(可執行文件、動態庫等)
    啓動APP時,dyld所作的事情有
    1.裝載APP的可執行文件,同時會遞歸加載全部依賴的動態庫
    2.當dyld把可執行文件、動態庫都裝載完畢後,會通知Runtime進行下一步的處理git

  • 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 所管理github

  • main
    1.APP的啓動由dyld主導,將可執行文件加載到內存,順便加載全部依賴的動態庫
    2.並由runtime負責加載成objc定義的結構
    3.全部初始化工做結束後,dyld就會調用main函數
    4.接下來就是UIApplicationMain函數,AppDelegate的application:didFinishLaunchingWithOptions:方法緩存

優化方案

1、dyld

  • 減小動態庫、合併一些動態庫(按期清理沒必要要的動態庫)
  • 減小Objc類、分類的數量、減小Selector數量(按期清理沒必要要的類、分類)
  • 減小C++虛函數數量
  • Swift儘可能使用struct

2、runtime

用+initialize方法和dispatch_once取代全部的__attribute__((constructor))、C++靜態構造器、ObjC的+load性能優化

3、main

  • 在不影響用戶體驗的前提下,儘量將一些操做延遲,不要所有都放在finishLaunching方法中
  • 按需加載

後面會分享本身的優化過程

相關文章
相關標籤/搜索