1. App啟動(dòng)過程
解析Info.plist
- 加載相關(guān)信息,例如如閃屏
- 沙箱建立、權(quán)限檢查-
Mach-O加載
- 如果是胖二進(jìn)制文件,尋找合適當(dāng)前CPU類別的部分
- 加載所有依賴的Mach-O文件(遞歸調(diào)用Mach-O加載的方法)
- 定位內(nèi)部、外部指針引用,例如字符串、函數(shù)等
- 執(zhí)行聲明為attribute((constructor))的C函數(shù)
- 加載類擴(kuò)展(Category)中的方法
- C++靜態(tài)對(duì)象加載、調(diào)用ObjC的 +load 函數(shù)
-
程序執(zhí)行
- 調(diào)用main()
- 調(diào)用UIApplicationMain()
- 調(diào)用applicationWillFinishLaunching
2. 如何測(cè)量啟動(dòng)過程耗時(shí)
冷啟動(dòng)比熱啟動(dòng)重要
當(dāng)用戶按下home鍵的時(shí)候,iOS的App并不會(huì)馬上被kill掉,還會(huì)繼續(xù)存活若干時(shí)間。理想情況下,用戶點(diǎn)擊App的圖標(biāo)再次回來的時(shí)候,App幾乎不需要做什么,就可以還原到退出前的狀態(tài),繼續(xù)為用戶服務(wù)。這種持續(xù)存活的情況下啟動(dòng)App,我們稱為熱啟動(dòng),相對(duì)而言冷啟動(dòng)就是App被kill掉以后一切從頭開始啟動(dòng)的過程。我們這里只討論App冷啟動(dòng)的情況。
main()函數(shù)之前
在不越獄的情況下,以往很難精確的測(cè)量在main()函數(shù)之前的啟動(dòng)耗時(shí),因而我們也往往容易忽略掉這部分?jǐn)?shù)據(jù)。小型App確實(shí)不需要太過關(guān)注這部分。但如果是大型App(自定義的動(dòng)態(tài)庫超過50個(gè)、或編譯結(jié)果二進(jìn)制文件超過30MB),這部分耗時(shí)將會(huì)變得突出。所幸,蘋果已經(jīng)在Xcode中加入這部分的支持。
main()函數(shù)之后
從main()函數(shù)開始至applicationWillFinishLaunching結(jié)束,我們統(tǒng)一稱為main()函數(shù)之后的部分。
3. 影響啟動(dòng)性能的因素
App啟動(dòng)過程中每一個(gè)步驟都會(huì)影響啟動(dòng)性能,但是有些部分所消耗的時(shí)間少之又少,另外有些部分根本無法避免,考慮到投入產(chǎn)出比,我們只列出我們可以優(yōu)化的部分:
main()函數(shù)之前耗時(shí)的影響因素
- 動(dòng)態(tài)庫加載越多,啟動(dòng)越慢。
- ObjC類越多,啟動(dòng)越慢
- C的constructor函數(shù)越多,啟動(dòng)越慢
- C++靜態(tài)對(duì)象越多,啟動(dòng)越慢
- ObjC的+load越多,啟動(dòng)越慢
main()函數(shù)之后耗時(shí)的影響因素
- 執(zhí)行main()函數(shù)的耗時(shí)
- 執(zhí)行applicationWillFinishLaunching的耗時(shí)
- rootViewController及其childViewController的加載、view及其subviews的加載
這些操作地方都是耗時(shí)影響主線程的問題,需要異步后臺(tái)線程,處理然后主線程更新,展位圖作占位。