好的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方法中
按需加載
後面會分享本身的優化過程