針對APP性能優(yōu)化很重要一點在于APP啟動時候啟動速度的優(yōu)化拦止,避免在啟動時處理過多業(yè)務(wù)邏輯導(dǎo)致啟動速度慢哩照,使用戶體驗比較一般弧烤,以下是對了解到的資料做盡可能簡單易懂的整理涧黄。
程序啟動總時間包含:t(App總啟動時間) = t1(main()之前的加載時間) + t2(main()之后的加載時間)。
t1 = 系統(tǒng)dylib(動態(tài)鏈接庫)和自身App可執(zhí)行文件的加載:
App開始啟動后恢恼,系統(tǒng)首先加載可執(zhí)行文件(自身App的所有.o文件的集合)民傻,然后加載動態(tài)鏈接庫dyld,dyld是一個專門用來加載動態(tài)鏈接庫的庫。 執(zhí)行從dyld開始漓踢,dyld從可執(zhí)行文件的依賴開始, 遞歸加載所有的依賴動態(tài)鏈接庫牵署。
動態(tài)鏈接庫包括:iOS 中用到的所有系統(tǒng) framework,加載OC runtime方法的libobjc喧半,系統(tǒng)級別的libSystem奴迅,例如libdispatch(GCD)和libsystem_blocks (Block)。
t2 = main方法執(zhí)行之后到AppDelegate類中的- (BOOL)Application:(UIApplication )Application didFinishLaunchingWithOptions:(NSDictionary )launchOptions方法執(zhí)行結(jié)束前這段時間挺据,主要是構(gòu)建第一個界面取具,并完成渲染展示。
重點: 獲取APP啟動時間—
首先在 main.m 添加如下代碼
CFAbsoluteTime StartTime;
int main(int argc, char * argv[]) {
StartTime = CFAbsoluteTimeGetCurrent();
然后在 AppDelegate.m 的開頭聲明
extern CFAbsoluteTime StartTime;
最后在AppDelegate.m 的 didFinishLaunchingWithOptions 中添加
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"App啟動時間--%f",(CFAbsoluteTimeGetCurrent()-StartTime));
});
最終打印結(jié)果如下:
啟動時間
一扁耐、調(diào)用main函數(shù)前 編譯加載自身可執(zhí)行文件和動態(tài)鏈接庫dyld以及系統(tǒng)framework等耗時優(yōu)化暇检,
總結(jié)一下:
對于main()調(diào)用之前的耗時我們可以優(yōu)化的點有:
- 減少不必要的framework,因為動態(tài)鏈接比較耗時
- check framework應(yīng)當設(shè)為optional和required婉称,如果該framework在當前App支持的所有iOS系統(tǒng)版本都存在块仆,那么就設(shè)為required,否則就設(shè)為optional王暗,因為optional會有些額外的檢查
- 合并或者刪減一些OC類悔据,關(guān)于清理項目中沒用到的類:{1.刪減一些無用的靜態(tài)變量 2.刪減沒有被調(diào)用到或者已經(jīng)廢棄的方法 3.將不必須在+load方法中做的事情延遲到+initialize中 4.盡量不要用C++虛函數(shù)(創(chuàng)建虛函數(shù)表有開銷)}
二、main函數(shù)調(diào)用之后的加載時間
在main()被調(diào)用之后俗壹,App的主要工作就是初始化必要的服務(wù)科汗,顯示首頁內(nèi)容等。而我們的優(yōu)化也是圍繞如何能夠快速展現(xiàn)首頁來開展绷雏。 App通常在AppDelegate類中的- (BOOL)Application:(UIApplication )Application didFinishLaunchingWithOptions:(NSDictionary )launchOptions方法中創(chuàng)建首頁需要展示的view头滔,然后在當前runloop的末尾,主動調(diào)用CA::Transaction::commit完成視圖的渲染之众。
而視圖的渲染主要涉及三個階段:
- 準備階段 這里主要是圖片的解碼
- 布局階段 首頁所有UIView的- (void)layoutSubViews()運行
- 繪制階段 首頁所有UIView的- (void)drawRect:(CGRect)rect運行
再加上啟動之后必要服務(wù)的啟動拙毫、必要數(shù)據(jù)的創(chuàng)建和讀取依许,這些就是我們可以嘗試優(yōu)化的地方
因此棺禾,對于main()函數(shù)調(diào)用之后我們可以優(yōu)化的點有:
- 不使用xib,直接視用代碼加載首頁視圖
- NSUserDefaults實際上是在Library文件夾下會生產(chǎn)一個plist文件峭跳,如果文件太大的話一次能讀取到內(nèi)存中可能很耗時膘婶,這個影響需要評估,如果耗時很大的話需要拆分(需考慮老版本覆蓋安裝兼容問題)
- 每次用NSLog方式打印會隱式的創(chuàng)建一個Calendar蛀醉,因此需要刪減啟動時各業(yè)務(wù)方打的log悬襟,或者僅僅針對內(nèi)測版輸出log
- 梳理應(yīng)用啟動時發(fā)送的所有網(wǎng)絡(luò)請求,是否可以統(tǒng)一在異步線程請求
- 首頁方法對于viewDidLoad以及viewWillAppear方法中盡量去嘗試少做拯刁,晚做脊岳,不做。
聲明下這里有借鑒到今日頭條iOS客戶端啟動速度優(yōu)化:https://techblog.toutiao.com/2017/01/17/iosspeed/