重學(xué)iOS系列之APP啟動(dòng)(七)優(yōu)化總結(jié)

前文已經(jīng)通過源碼分析以及實(shí)戰(zhàn)演練帶領(lǐng)讀者學(xué)習(xí)了APP啟動(dòng)的整個(gè)過程,既然知識(shí)已經(jīng)學(xué)了,就要學(xué)以致用。

APP啟動(dòng)-優(yōu)化總結(jié):

main()函數(shù)之前的優(yōu)化:

1、減少動(dòng)態(tài)庫(kù)加載。每個(gè)庫(kù)本身都有依賴關(guān)系,蘋果公司建議使用更少的動(dòng)態(tài)庫(kù),并且建議 在使用動(dòng)態(tài)庫(kù)的數(shù)量較多時(shí),盡量將多個(gè)動(dòng)態(tài)庫(kù)進(jìn)行合并。數(shù)量上,蘋果公司最多可以支 持 6 個(gè)非系統(tǒng)動(dòng)態(tài)庫(kù)合并為一個(gè)。

2、將動(dòng)態(tài)庫(kù)轉(zhuǎn)換成靜態(tài)庫(kù)。

3、進(jìn)行代碼瘦身,合并或刪除無(wú)效的ObjC類、Category、方法、C++ 靜態(tài)全局變量等。

4、+load() 方法里的內(nèi)容可以放到首屏渲染完成后再執(zhí)行,或使用 +initialize() 方法替換 掉。因?yàn)?,在一個(gè) +load() 方法里,進(jìn)行運(yùn)行時(shí)方法替換操作會(huì)帶來(lái) 4 毫秒的消耗。不 要小看這 4 毫秒,積少成多,執(zhí)行 +load() 方法對(duì)啟動(dòng)速度的影響會(huì)越來(lái)越大。

5、控制 C++ 全局變量的數(shù)量。

6、編譯期clang插樁優(yōu)化。


這是main()函數(shù)之前的優(yōu)化,那么main()函數(shù)之后的優(yōu)化要怎么做呢?

其實(shí)這個(gè)部分才是重點(diǎn)中的重點(diǎn),因?yàn)榇蟛糠諥PP只要對(duì)main()函數(shù)后的時(shí)間做好優(yōu)化就能滿足400ms的啟動(dòng)要求。而且這部分的優(yōu)化更貼合大眾,相對(duì)也更簡(jiǎn)單。

main() 函數(shù)執(zhí)行后的階段,指的是從 main() 函數(shù)執(zhí)行開始,到 appDelegate 的

didFinishLaunchingWithOptions 方法里首屏渲染相關(guān)方法執(zhí)行完成。 首頁(yè)的業(yè)務(wù)代碼都是要在這個(gè)階段,也就是首屏渲染前執(zhí)行的,主要包括了:

首屏初始化所需配置文件的讀寫操作; 首屏列表大數(shù)據(jù)的讀取; 首屏渲染的大量計(jì)算等。

很多時(shí)候,開發(fā)者會(huì)把各種初始化工作都放到這個(gè)階段執(zhí)行,導(dǎo)致渲染完成滯后。更加優(yōu)化 的開發(fā)方式,應(yīng)該是從功能上梳理出哪些是首屏渲染必要的初始化功能,哪些是 App 啟動(dòng) 必要的初始化功能,而哪些是只需要在對(duì)應(yīng)功能開始使用時(shí)才需要初始化的。梳理完之后, 將這些初始化功能分別放到合適的階段進(jìn)行。

1、功能級(jí)別的啟動(dòng)優(yōu)化

優(yōu)化的思路是: main() 函數(shù)開始執(zhí)行后到首屏渲染完成前只處理首屏相關(guān)的業(yè)務(wù),其他非 首屏業(yè)務(wù)的初始化、監(jiān)聽注冊(cè)、配置文件讀取等都放到首屏渲染完成后去做。

具體可以考慮從這些角度優(yōu)化:

1、用純代碼的方式,而不是 xib/Storyboard,來(lái)加載首頁(yè)視圖

2、延遲暫時(shí)不需要的二方/三方庫(kù)加載;

3、延遲執(zhí)行部分業(yè)務(wù)邏輯和 UI 配置;

4、延遲加載/懶加載部分視圖;

5、避免首屏加載時(shí)大量的本地/網(wǎng)絡(luò)數(shù)據(jù)讀??;

6、在 release 包中移除 NSLog 打??;

7、在視覺可接受的范圍內(nèi),壓縮頁(yè)面中的圖片大小;

……

如果首屏為 H5 頁(yè)面,針對(duì)它的優(yōu)化,參考VasSonic的原理,可以從這幾個(gè)角度入手:

終端耗時(shí)

webView 預(yù)加載:在 App 啟動(dòng)時(shí)期預(yù)先加載了一次 webView,通過創(chuàng)建空的 webView,預(yù)先啟動(dòng) Web 線程,完成一些全局性的初始化工作,對(duì)二次創(chuàng)建 webView 能有數(shù)百毫秒的提升。

頁(yè)面耗時(shí)(靜態(tài)頁(yè)面)

靜態(tài)直出:服務(wù)端拉取數(shù)據(jù)后通過 Node.js 進(jìn)行渲染,生成包含首屏數(shù)據(jù)的 HTML 文件,發(fā)布到 CDN 上,webView 直接從 CDN 上獲取;

離線預(yù)推:使用離線包。

頁(yè)面耗時(shí)(經(jīng)常需要?jiǎng)討B(tài)更新的頁(yè)面)

并行加載:WebView 的打開和資源的請(qǐng)求并行;

動(dòng)態(tài)緩存:動(dòng)態(tài)頁(yè)面緩存在客戶端,用戶下次打開的時(shí)候先打開緩存頁(yè)面,然后再刷新;

動(dòng)靜分離:將頁(yè)面分為靜態(tài)模板和動(dòng)態(tài)數(shù)據(jù),根據(jù)不同的啟動(dòng)場(chǎng)景進(jìn)行不同的刷新方案;

預(yù)加載:提前拉取需要的增量更新數(shù)據(jù)。


2、方法級(jí)別的啟動(dòng)優(yōu)化

第一種方法是,定時(shí)抓取主線程上的方法調(diào)用堆棧,計(jì)算一段時(shí)間里各個(gè)方法的耗時(shí)。Xcode 工具套件里自帶的 Time Profiler ,采用的就是這種方式。

可以參考:iOS 如何抓取線程的“方法調(diào)用棧”

第二種方法是,對(duì) objc_msgSend 方法進(jìn)行 hook 來(lái)掌握所有方法的執(zhí)行耗時(shí)。

可以參考:自己做一個(gè)工具監(jiān)控App的啟動(dòng)耗時(shí)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容