前言
在WWDC 2016上首次提到了關于App應用啟動速度優化的話題:Session 406 Optimizing App Startup Time .該Session上Apple建議一個App完整的啟動時間應該保證400ms之內,而若超過20s后還未完全啟動App,那么App進程就會被系統殺死.而如何Debug和優化應用啟動的時間,官方提出一系列方法來關注應用啟動時執行main()
前究竟干了些什么.而通過這個Session,你會了解到以下內容:
- 如何獲得應用加載的時間
- 執行程序入門的代碼前App加載過程中的流程
- 如何優化App的加載時間
測量Pre-main Time
一個App在執行main函數前包括app delegate的系列方法如applicationWillFinishLaunching
時,會做許多系統級別的準備.而在iOS10之前,開發者很難清楚自己App為何啟動加載慢.而通過在工程的scheme中添加環境變量DYLD_PRINT_STATISTICS,設置Value為1,App啟動加載時就會有啟動過程的日志輸出. 現在(iOS 10之后)Apple對DYLD_PRINT_STATISTICS的日志輸出結果進行了簡化,使得更容易讓開發者理解.
嘗試在iPad (使用iOS10 beta 3)上對一個純OC項目設置該環境變量后,有了以下輸出信息.
Total pre-main time: 74.37 milliseconds (100.0%)
dylib loading time: 41.05 milliseconds (55.2%)
rebase/binding time: 8.10 milliseconds (10.9%)
ObjC setup time: 9.87 milliseconds (13.2%)
initializer time: 15.23 milliseconds (20.4%)
slowest intializers :
libSystem.B.dylib : 6.58 milliseconds (8.8%)
libBacktraceRecording.dylib : 6.27 milliseconds (8.4%)
輸出內容展示了系統調用main()函前主要進行的工作內容和時間花費,Session上也對每一階段加載過程具體內容進行了詳細的敘述,有興趣地可觀看該Session.
啟動優化
那么如何盡可能的減少pre-main花費的時間呢,主要就從輸出日志給出的四個階段下手:
對動態庫加載的時間優化.每個App都進行動態庫加載,其中系統級別的動態庫占據了絕大數,而針對系統級別的動態庫都是經過系統高度優化的,不用擔心時間的花費.開發者應該關注于自己集成到App的那些動態庫,這也是最能消耗加載時間的地方.對此Apple建議減少在App里開發者的動態庫集成或者有可能地將其多個動態庫最終集成一個動態庫后進行導入, 盡量保證將App現有的非系統級的動態庫個數保證在6個以內.
減少Appp的Objective-C類,分類和的唯一Selector的個數.這樣做主要是為了加快程序的整個動態鏈接, 在進行動態庫的重定位和綁定(Rebase/binding)過程中減少指針修正的使用,加快程序機器碼的生成.
減少Objc運行初始化的時間花費.主要是類的注冊,分類的注冊,唯一選擇器的存在,以及涉及子父類內存布局的
Non Fragile ivars
偏移的更新,都會影響Objective-C運行時初始化的時間消耗.使用initialize方法進行必要的初始化工作.用
+initialize
方法替換調用原先在OC的+load
方法中執行初始代碼工作,從而加快所有類文件的加載速度.
結尾
最后演講者對加載啟動優化的整體概括了Session所要傳達的內容:
- 使用DYLD_PRINT_STATISTICS測試啟動加載時間
- 減少自定義的動態庫集成
- 精簡原有的Objective-C類和代碼
- 移除靜態的初始化操作
- 使用更多的Swift代碼