app啟動(dòng)分為冷啟動(dòng)和熱啟動(dòng)兩種。所謂的冷啟動(dòng)和熱啟動(dòng)主要取決于該app進(jìn)程是否在系統(tǒng)中。我們主要考慮的是冷啟動(dòng)的優(yōu)化,因?yàn)檫@才是一個(gè)完整的啟動(dòng)過(guò)程,熱啟動(dòng)中我們能干涉的其實(shí)很少
- main函數(shù)之前
可以通過(guò)添加添加環(huán)境變量 DYLD_PRINT_STATISTICS 來(lái)查看main函數(shù)執(zhí)行之前都做了什么,同時(shí)也可以看出對(duì)應(yīng)消耗的時(shí)間。- main函數(shù)執(zhí)行之前主要做了以下幾種事情
Total pre-main time: 17.00 milliseconds (100.0%)
dylib loading time: 140.89 milliseconds (828.5%)
rebase/binding time: 126687488.7 seconds (247154424.8%)
ObjC setup time: 16.27 milliseconds (95.7%)
initializer time: 57.75 milliseconds (339.6%)
slowest intializers :
libSystem.B.dylib : 3.70 milliseconds (21.7%)
libBacktraceRecording.dylib : 5.09 milliseconds (29.9%)
libobjc.A.dylib : 1.01 milliseconds (5.9%)
CoreFoundation : 1.24 milliseconds (7.3%)
Foundation : 0.35 milliseconds (2.1%)
libMainThreadChecker.dylib : 43.83 milliseconds (257.7%)
libLLVMContainer.dylib : 1.18 milliseconds (6.9%)
1、動(dòng)態(tài)庫(kù)的加載
對(duì)應(yīng)的是dylib loading time可以看到其加載時(shí)間
優(yōu)化建議
這里主要的優(yōu)化建議是減少動(dòng)態(tài)庫(kù)的加載,蘋果建議更少的使用動(dòng)態(tài)庫(kù),如果動(dòng)態(tài)庫(kù)的數(shù)量較多的時(shí)候,盡量將多個(gè)動(dòng)態(tài)庫(kù)合并,數(shù)量上最多支持6個(gè)非系統(tǒng)動(dòng)態(tài)庫(kù)的合并-
2、偏移修正和符號(hào)綁定
對(duì)應(yīng)的是rebase/binding time- 偏移修正
任何App生成的二進(jìn)制文件中的方法、函數(shù)都會(huì)有個(gè)地址,而這個(gè)地址是相對(duì)于當(dāng)前二進(jìn)制文件中的偏移地址,但是到了運(yùn)行時(shí)系統(tǒng)會(huì)隨機(jī)生成一個(gè)數(shù)值添加到二進(jìn)制文件的頭部(ASLR安全機(jī)制下文中會(huì)有講解),所以此時(shí)函數(shù)、方法的地址就是 隨機(jī)分配的數(shù)值+偏移地址 這個(gè)過(guò)程就是偏移修正 - 符號(hào)綁定
動(dòng)態(tài)庫(kù)不像是靜態(tài)庫(kù),靜態(tài)庫(kù)實(shí)在編譯時(shí)期就將對(duì)應(yīng)使用到的代碼一起打包生成了mach-o文件,所以此時(shí)使用到的靜態(tài)庫(kù)的方法、函數(shù)其實(shí)就和自定義的方法、函數(shù)差不多了,能夠直接獲取到對(duì)應(yīng)的地址,但是動(dòng)態(tài)庫(kù)在編譯階段是不會(huì)被打包進(jìn)mach-o文件的,但是此時(shí)又用到了動(dòng)態(tài)庫(kù)中的方法,例如用到了NSLog方法,此時(shí)就會(huì)生成一個(gè)!NSLog 符號(hào)此時(shí)這個(gè)符號(hào)會(huì)隨機(jī)指向一個(gè)地址,當(dāng)運(yùn)行時(shí),此時(shí)動(dòng)態(tài)庫(kù)被加載到內(nèi)存,此時(shí)就可以拿到動(dòng)態(tài)庫(kù)對(duì)應(yīng)的方法、函數(shù)的地址,所以此時(shí)就需要將!NSLog這個(gè)符號(hào)綁定到相應(yīng)的地址上去(dyld做的),這個(gè)過(guò)程就叫做符號(hào)綁定
- 偏移修正
3、類的注冊(cè)
對(duì)應(yīng)的是ObjC setup time
優(yōu)化建議
刪除啟動(dòng)后不會(huì)去使用的類4、執(zhí)行l(wèi)oad和構(gòu)造函數(shù)
對(duì)應(yīng)的是initializer time
優(yōu)化建議
減少使用load方法相應(yīng)的可以將load中的實(shí)現(xiàn)放在+initialize()方法中去,因?yàn)橐话阋粋€(gè)load方法的執(zhí)行需要耗時(shí)4毫秒,而且如果類中實(shí)現(xiàn)了load那么相對(duì)應(yīng)類的加載就要提前到read_image方法中去執(zhí)行,如果沒(méi)有實(shí)現(xiàn)load類的加載則會(huì)方法第一次發(fā)送消息的時(shí)候加載,-
main函數(shù)之后
這個(gè)階段主要是指main函數(shù)執(zhí)行開始到首屏渲染完成方法執(zhí)行完畢。
這個(gè)階段主要做的工作包括:1、第三方SDK初始化
2、自定義工具類初始化
3、首屏數(shù)據(jù)的加載
4、首屏渲染的一些計(jì)算
優(yōu)化建議
只處理首屏渲染相關(guān)的任務(wù),其他非首屏的業(yè)務(wù)例如初始化、注冊(cè)監(jiān)聽、配置文件的讀取等等都放在首頁(yè)渲染完成之后去做,當(dāng)然也可以開辟一個(gè)線程去處理這些事情。盡量不要占用主線程
自己的業(yè)務(wù)邏輯的優(yōu)化,已經(jīng)廢棄的不需要用的邏輯代碼、方法、函數(shù)都刪除掉,減少每個(gè)流程的耗時(shí)
啟動(dòng)時(shí)期的頁(yè)面盡量避免使用xib、storyboard(中間會(huì)有個(gè)轉(zhuǎn)換的過(guò)程也是需要耗時(shí)的)UI的主框架盡量使用純代碼