前言
什么情況下要去做啟動(dòng)優(yōu)化?
APP啟動(dòng)優(yōu)化,一般指的是冷啟動(dòng),因?yàn)槔鋯?dòng)過(guò)程中要做的事情有點(diǎn)多。但是什么情況下才要去做這個(gè)優(yōu)化?比如啟動(dòng)時(shí)間是多少的情況下才算是時(shí)間過(guò)長(zhǎng)了?
蘋果建議的是400ms以內(nèi)。如果啟動(dòng)時(shí)間超過(guò)20s,還會(huì)被系統(tǒng)強(qiáng)殺掉(感覺(jué)用戶等待5s都算很長(zhǎng)了??)。
另外對(duì)于用戶來(lái)說(shuō),從點(diǎn)擊圖標(biāo)到app首頁(yè)出現(xiàn)在屏幕上才算是啟動(dòng)完成,因此要評(píng)估從點(diǎn)擊圖標(biāo)到首頁(yè)呈現(xiàn)整個(gè)階段的時(shí)間。
怎么取檢測(cè)冷啟動(dòng)時(shí)間?
以APP的進(jìn)程創(chuàng)建時(shí)間作為冷啟動(dòng)的起始時(shí)間
+ (BOOL)processInfoForPID:(int)pid procInfo:(struct kinfo_proc*)procInfo
{
int cmd[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
size_t size = sizeof(*procInfo);
return sysctl(cmd, sizeof(cmd)/sizeof(*cmd), procInfo, &size, NULL, 0) == 0;
}
+ (NSTimeInterval)processStartTime
{
struct kinfo_proc kProcInfo;
if ([self processInfoForPID:[[NSProcessInfo processInfo] processIdentifier] procInfo:&kProcInfo]) {
return kProcInfo.kp_proc.p_un.__p_starttime.tv_sec * 1000.0 + kProcInfo.kp_proc.p_un.__p_starttime.tv_usec / 1000.0;
} else {
NSAssert(NO, @"無(wú)法取得進(jìn)程的信息");
return 0;
}
}
分析耗時(shí)位置
APP從點(diǎn)擊圖標(biāo)到首頁(yè)展示主要有以下階段:
加載動(dòng)態(tài)庫(kù),進(jìn)行rebase和bind操作
dyld從主程序文件的header中獲取到需要加載哪些動(dòng)態(tài)庫(kù),然后去尋找加載。
這一步對(duì)于系統(tǒng)的動(dòng)態(tài)庫(kù),系統(tǒng)做了緩存機(jī)制,耗時(shí)其實(shí)比較少(如果其他應(yīng)用加載過(guò)的話)。
但是對(duì)于我們的embed framework,要依次的進(jìn)行簽名校驗(yàn),加載。
動(dòng)態(tài)庫(kù)加載后,還要依次進(jìn)行rebase和bind操作來(lái)修正指針。
因此個(gè)人覺(jué)得,如果內(nèi)嵌的動(dòng)態(tài)庫(kù)比較多的話,可以考慮使用靜態(tài)庫(kù)。靜態(tài)庫(kù)在編譯的時(shí)候就已經(jīng)link進(jìn)入app的可執(zhí)行文件里,運(yùn)行期間不需要再動(dòng)態(tài)加載
objc setup 和 initializers
- 注冊(cè)objc類,綁定category到對(duì)應(yīng)的類,插入方法,屬性等操作。
- 調(diào)用類的+load函數(shù)
- c++的構(gòu)造函數(shù)
- 非基本類型c++靜態(tài)全局變量的創(chuàng)建
從上面兩步看,如果類越多,+load方法實(shí)現(xiàn)越多,c++構(gòu)造函數(shù)越多,c++靜態(tài)對(duì)象越多,啟動(dòng)就會(huì)越慢。因此要經(jīng)常刪除無(wú)用的類和方法以及盡量減少在+load方法里做操作
接下來(lái)就是main函數(shù)之后。
didFinish……
這個(gè)代理方法里,盡量減少一些操作,或者一些不必要的操作延后處理。
參考地址:https://tech.meituan.com/2018/12/06/waimai-ios-optimizing-startup.html