前文已經(jīng)通過源碼分析以及實戰(zhàn)演練帶領(lǐng)讀者學(xué)習(xí)了APP啟動的整個過程冈闭,既然知識已經(jīng)學(xué)了,就要學(xué)以致用抖单。
APP啟動-優(yōu)化總結(jié):
main()函數(shù)之前的優(yōu)化:
1拒秘、減少動態(tài)庫加載号显。每個庫本身都有依賴關(guān)系,蘋果公司建議使用更少的動態(tài)庫躺酒,并且建議 在使用動態(tài)庫的數(shù)量較多時押蚤,盡量將多個動態(tài)庫進行合并。數(shù)量上羹应,蘋果公司最多可以支 持 6 個非系統(tǒng)動態(tài)庫合并為一個揽碘。
2、將動態(tài)庫轉(zhuǎn)換成靜態(tài)庫园匹。
3雳刺、進行代碼瘦身,合并或刪除無效的ObjC類裸违、Category掖桦、方法、C++ 靜態(tài)全局變量等供汛。
4枪汪、+load() 方法里的內(nèi)容可以放到首屏渲染完成后再執(zhí)行,或使用 +initialize() 方法替換 掉怔昨。因為雀久,在一個 +load() 方法里,進行運行時方法替換操作會帶來 4 毫秒的消耗趁舀。不 要小看這 4 毫秒赖捌,積少成多,執(zhí)行 +load() 方法對啟動速度的影響會越來越大矮烹。
5越庇、控制 C++ 全局變量的數(shù)量。
6奉狈、編譯期clang插樁優(yōu)化悦荒。
這是main()函數(shù)之前的優(yōu)化,那么main()函數(shù)之后的優(yōu)化要怎么做呢嘹吨?
其實這個部分才是重點中的重點,因為大部分APP只要對main()函數(shù)后的時間做好優(yōu)化就能滿足400ms的啟動要求境氢。而且這部分的優(yōu)化更貼合大眾蟀拷,相對也更簡單。
main() 函數(shù)執(zhí)行后的階段萍聊,指的是從 main() 函數(shù)執(zhí)行開始问芬,到 appDelegate 的
didFinishLaunchingWithOptions 方法里首屏渲染相關(guān)方法執(zhí)行完成。 首頁的業(yè)務(wù)代碼都是要在這個階段寿桨,也就是首屏渲染前執(zhí)行的此衅,主要包括了:
首屏初始化所需配置文件的讀寫操作; 首屏列表大數(shù)據(jù)的讀取; 首屏渲染的大量計算等强戴。
很多時候,開發(fā)者會把各種初始化工作都放到這個階段執(zhí)行挡鞍,導(dǎo)致渲染完成滯后骑歹。更加優(yōu)化 的開發(fā)方式,應(yīng)該是從功能上梳理出哪些是首屏渲染必要的初始化功能墨微,哪些是 App 啟動 必要的初始化功能道媚,而哪些是只需要在對應(yīng)功能開始使用時才需要初始化的。梳理完之后翘县, 將這些初始化功能分別放到合適的階段進行最域。
1、功能級別的啟動優(yōu)化
優(yōu)化的思路是: main() 函數(shù)開始執(zhí)行后到首屏渲染完成前只處理首屏相關(guān)的業(yè)務(wù)锈麸,其他非 首屏業(yè)務(wù)的初始化镀脂、監(jiān)聽注冊、配置文件讀取等都放到首屏渲染完成后去做忘伞。
具體可以考慮從這些角度優(yōu)化:
1薄翅、用純代碼的方式,而不是 xib/Storyboard虑省,來加載首頁視圖
2匿刮、延遲暫時不需要的二方/三方庫加載;
3探颈、延遲執(zhí)行部分業(yè)務(wù)邏輯和 UI 配置熟丸;
4、延遲加載/懶加載部分視圖伪节;
5光羞、避免首屏加載時大量的本地/網(wǎng)絡(luò)數(shù)據(jù)讀取怀大;
6纱兑、在 release 包中移除 NSLog 打印化借;
7潜慎、在視覺可接受的范圍內(nèi),壓縮頁面中的圖片大斜涂怠铐炫;
……
如果首屏為 H5 頁面,針對它的優(yōu)化蒜焊,參考VasSonic的原理倒信,可以從這幾個角度入手:
終端耗時
webView 預(yù)加載:在 App 啟動時期預(yù)先加載了一次 webView,通過創(chuàng)建空的 webView泳梆,預(yù)先啟動 Web 線程鳖悠,完成一些全局性的初始化工作榜掌,對二次創(chuàng)建 webView 能有數(shù)百毫秒的提升。
頁面耗時(靜態(tài)頁面)
靜態(tài)直出:服務(wù)端拉取數(shù)據(jù)后通過 Node.js 進行渲染乘综,生成包含首屏數(shù)據(jù)的 HTML 文件憎账,發(fā)布到 CDN 上,webView 直接從 CDN 上獲锐鼠哥;
離線預(yù)推:使用離線包。
頁面耗時(經(jīng)常需要動態(tài)更新的頁面)
并行加載:WebView 的打開和資源的請求并行看政;
動態(tài)緩存:動態(tài)頁面緩存在客戶端朴恳,用戶下次打開的時候先打開緩存頁面,然后再刷新允蚣;
動靜分離:將頁面分為靜態(tài)模板和動態(tài)數(shù)據(jù)于颖,根據(jù)不同的啟動場景進行不同的刷新方案;
預(yù)加載:提前拉取需要的增量更新數(shù)據(jù)嚷兔。
2森渐、方法級別的啟動優(yōu)化
第一種方法是,定時抓取主線程上的方法調(diào)用堆棧冒晰,計算一段時間里各個方法的耗時同衣。Xcode 工具套件里自帶的 Time Profiler ,采用的就是這種方式壶运。
可以參考:iOS 如何抓取線程的“方法調(diào)用椖推耄”
第二種方法是,對 objc_msgSend 方法進行 hook 來掌握所有方法的執(zhí)行耗時蒋情。