啟動
啟動的過程一般是指從用戶點擊app圖標
開始到AppDelegate 的didFinishLaunching
方法執(zhí)行完成為止,其中嗜历,啟動也分為冷啟動和熱啟動
冷啟動
:內(nèi)存中不包含app相關數(shù)據(jù)的啟動撵割,一般我們可以通過重啟手機來實現(xiàn)冷啟動熱啟動
:是指殺掉app進程后,數(shù)據(jù)仍然存在時的啟動
而我們這里所說的啟動優(yōu)化桅狠,一般是指冷啟動情況
下的兰怠,這種情況下的啟動主要分為兩部分:
T1 :
pre-main
階段垃僚,即main函數(shù)之前,操作系統(tǒng)加載App可執(zhí)行文件到內(nèi)存错妖,執(zhí)行一系列的加載&鏈接等工作绿鸣,簡單來說,就是dyld加載過程
T2:main函數(shù)之后暂氯,即從main函數(shù)開始潮模,到Appdelegate 的
didFinishLaunching
方法執(zhí)行完成為止,主要是構建第一個界面痴施,并完成渲染
所以擎厢,T1+T2
的過程 就是 從用戶點擊App圖標到用戶能看到app主界面的過程,即需要啟動優(yōu)化的部分
pre-main階段的優(yōu)化
在iOS-底層原理 15:dyld加載流程中辣吃,已經(jīng)了解過了dyld的加載流程动遭。pre-main階段的啟動時間其實就是dyld加載過程的時間
針對main函數(shù)之前的啟動時間,蘋果提供了內(nèi)建的測量方法神得,在Edit Scheme -> Run -> Arguments ->Environment Variables
點擊+添加環(huán)境變量 DYLD_PRINT_STATISTICS
設為 1
)厘惦,然后運行,以下是iPhone7p正常啟動的pre-main時間(以WeChat為例)
說明
pre-main階段總共用時1.7s
dylib loading
time(動態(tài)庫耗時):主要是加載動態(tài)庫哩簿,用時320.32ms-
rebase/binding
time(偏移修正/符號綁定耗時)宵蕉,耗時160.52msrebase(偏移修正)
:任何一個app生成的二進制文件,在二進制文件內(nèi)部所有的方法节榜、函數(shù)調(diào)用羡玛,都有一個地址,這個地址是在當前二進制文件中的偏移地址
宗苍。一旦在運行時刻(即運行到內(nèi)存中)稼稿,每次系統(tǒng)都會隨機分配一個ASLR(Address Space Layout Randomization,地址空間布局隨機化)地址值
(是一個安全機制讳窟,會分配一個隨機的數(shù)值让歼,插入在二進制文件的開頭),例如挪钓,二進制文件中有一個 test方法是越,偏移值是0x0001耳舅,而隨機分配的ASLR
是0x1f00碌上,如果想訪問test方法倚评,其內(nèi)存地址(即真實地址)變?yōu)?ASLR+偏移值 = 運行時確定的內(nèi)存地址
(即0x1f00+0x0001 = 0x1f01)binding(綁定)
:,例如NSLog
方法馏予,在編譯時期生成的mach-o文件中天梧,會創(chuàng)建一個符號!NSLog
(目前指向一個隨機的地址)霞丧,然后在運行時(從磁盤加載到內(nèi)存中呢岗,是一個鏡像文件),會將真正的地址給符號(即在內(nèi)存中將地址與符號進行綁定蛹尝,是dyld
做的后豫,也稱為動態(tài)庫符號綁定
),一句話概括:綁定就是給符號賦值的過程
ObjC setup
time(OC類注冊的耗時):OC類越多突那,越耗時initializer
time(執(zhí)行l(wèi)oad和構造函數(shù)的耗時)
針對這幾部挫酿,有以下幾點優(yōu)化建議:
盡量
少用外部動態(tài)庫
,蘋果官方建議自定義的動態(tài)庫最好不要超過6個
愕难,如果超過6個早龟,需要合并
動態(tài)庫減少OC類,因為OC類越多猫缭,越耗時
將不必須在
+load
方法中做的事情延遲到+initialize
中葱弟,盡量不要用C++虛函數(shù)如果是swift,盡量使用
struct
main函數(shù)階段的優(yōu)化
在main函數(shù)之后的didFinishLaunching
方法中猜丹,主要是執(zhí)行了各種業(yè)務芝加,有很多并不是必須在這里立即執(zhí)行的,這種業(yè)務我們可以采取延遲加載射窒,防止影響啟動時間妖混。
在didFinishLaunching
中的業(yè)務主要分為三個類型
- 【第一類】初始化第三方sdk
- 【第二類】app運行環(huán)境配置
- 【第三類】自己工具類的初始化等
main函數(shù)階段的優(yōu)化建議主要有以下幾點:
減少啟動初始化的流程
,能懶加載的懶加載轮洋,能延遲的延遲制市,能放后臺初始化的放后臺,盡量不要占用主線程的啟動時間優(yōu)化代碼邏輯弊予,
去除非必須的代碼邏輯
祥楣,減少每個流程的消耗時間啟動階段能
使用多線程
來初始化的,就使用多線程盡量
使用純代碼
來進行UI框架的搭建汉柒,尤其是主UI框架误褪,例如UITabBarController。盡量避免使用Xib或者SB碾褂,相比純代碼而言兽间,這種更耗時刪除廢棄類、方法