天天看點

iOS啟動速度優化總結

       随着項目越做越大,代碼和業務量越來越多,這時候每次啟動APP的時候就會花費較長的時間,這對使用者來說體驗很不好。是以,針對APP啟動時間的優化還是很有必要的。

       關于APP啟動時間的分析和優化可以以main()為分界點,分為main()方法執行之前的加載時間(pre-main time)和main()之後的加載時間。那麼,如何定量的測量這兩個階段具體的執行時間呢,下面先給出測量方法,看一下自己項目啟動時間是否合理:

一、main()方法之前啟動時間的測量方法:

       在Xcode中添加環境變量參數DYLD_PRINT_STATISTICS即可,這樣運作APP時在控制台就會列印出pre-main花費的時間,如下圖:

iOS啟動速度優化總結
iOS啟動速度優化總結

如果想列印詳細的pre-main中各個過程花費的時間,可以再添加一個DYLD_PRINT_STATISTICS_DETAILS參數,這時你會看到pre-main time和total time的值不一樣,其實下邊的total time - debugger pause time就和上邊的pre-main time大概一緻了。如下圖:

iOS啟動速度優化總結
iOS啟動速度優化總結

PS:如果你想列印dyld裝載動态庫的順序,可以設定這個環境變量 DYLD_PRINT_LIBRARIES

二、main()方法之後的啟動時間的測量方法: 

   在main.m檔案中,定義一個全局變量:

CFAbsoluteTime startTime;

int main(int argc, char * argv[]) {
    startTime = CFAbsoluteTimeGetCurrent();           

   在AppDelegate.m檔案中didFinishLaunchingWithOptions方法return之前計算時間差:

double launchTime = CFAbsoluteTimeGetCurrent() - startTime;
 NSLog(@"launchTime = %f秒",launchTime);           

三、main()方法調用之前啟動過程的解析:

     App開始啟動後,系統核心(XNU)首先加載可執行檔案(自身App的所有.o檔案的集合),然後加載動态連結器dyld,dyld是一個專門用來加載動态連結庫的庫。 執行從dyld開始,dyld從可執行檔案的依賴開始, 遞歸加載所有的依賴動态連結庫。 

動态連結庫包括:iOS 中用到的所有系統 framework,加載OC runtime方法的libobjc,系統級别的libSystem,例如libdispatch(GCD)和libsystem_blocks (Block)。

    總結來說,main()方法調用前,啟動過程大體分為如下步驟: 

    1、核心加載可執行檔案

    2、load dylibs image (加載程式所需的動态庫鏡像檔案)

    3、Rebase image /  Bind image (由于ASLR(address space layout randomization)的存在,可執行檔案和動态連結庫在虛拟内  存中的加載位址每次啟動都不固定,是以需要修複鏡像中的資源指針)

    4、Objc setup (注冊Objc類、将Category中的方法插入方法清單)

    5、initializers (調用Objc類的+load()方法、調用C++類的構造函數)

   針對上邊各個啟動過程,我們可以做的優化有:

   1、減少動态庫的引用,将項目中不使用的Framework及時删除,将Xcode配置中General -> Linked Frameworks and Libraries中使用不到的系統庫不再引用。

   2、合并動态庫。

   3、盡量不使用内嵌(embedded)的dylib,加載内嵌dylib性能開銷較大。

   4、清理項目中備援的類、category。對于同一個類有多個category的,建議進行合并。

   5、将不必須在+load方法中做的事情延遲到+initialize中。

   6、盡量不要用C++虛函數(建立虛函數表有開銷),不要在C++構造函數中做大量耗時操作。

四、main()方法調用之後過程的解析: 

     main()方法調用之後,主要是didFinishLaunchingWithOptions方法中初始化必要的服務,顯示首頁内容等操作。這時候我們可以做的事情主要有:

     1、将一些不影響首頁展示的服務放到其他線程中去處理,或者延時處理和懶加載。延時處理可以監聽Runloop的狀态,當進入kCFRunLoopBeforeWaiting(即将休眠狀态)再去處理任務,最大限度的利用CPU等系統資源。

     2、使用Xcode的Instruments的Time Profiler工具,分析啟動過程中比較耗時的方法和操作,然後,進行具體的優化。

    3、重點關注TabBarController和首頁的性能,保證盡快的能展示出來。這兩個控制器及裡邊的view盡量用代碼進行布局,不使用storyboard和xib,如果在布局上想更進一步的優化,那就連autolayout(Massonry)都不要使用,直接使用frame進行布局。

    4、本地緩存。首頁的資料離線化,優先展示本地緩存資料,等待網絡資料傳回之後更新緩存并展示。

以上就是關于iOS用戶端啟動優化的相關總結,如有不同意見或者更好的方案,歡迎溝通交流。 

參考:

iOS啟動時間優化

今日頭條iOS用戶端啟動速度優化

iOS App從點選到啟動(介紹系統架構和底層知識較多)

APP從編譯到連結再到啟動的過程 

繼續閱讀