今是昨非

今是昨非

日出江花红胜火,春来江水绿如蓝

iOS 啟動時間優化

iOS 啟動時間優化 —— 相關#

背景#

iOS 的啟動時間優化有很多相關的文章,本來不打算寫,但是總歸是自己整理一遍印象更深刻。這裡打算從原理 - 實踐 - 面試相關三個方面來入手。首先要理解 APP 啟動的原理,啟動做了什麼?然後針對啟動過程中的事件哪些是開發可以進行優化的,去實踐?最後則是,面試相關,與啟動優化相關的面試有很多,筆者打算列舉一下,分別涉及到啟動的哪些問題。

啟動原理#

啟動分為冷啟動和熱啟動。冷啟動指的是 APP 進程被殺掉後,從零打開;熱啟動指的是,APP 進入後臺,再切換到前臺喚起到過程。這裡通常說的啟動優化,指的是冷啟動優化。(Ps: 這裡某些版本會出現,剛殺掉的 APP,立即再次打開,會直接閃退的問題,是系統的 Bug)。

冷啟動的過程分為main函數之前(pre-main)main函數之後兩個階段。

pre-main 階段#

就如很多文章說的:

pre-main 階段的過程分為dylibs loading ——> rebase/binding ——> ObjC setup ——> initializer四個部分。每個部分吧啦吧啦... 但每次問到這個時候,死記硬背出來真的累人😂。

為什麼會感覺困難呢?是因為不知道這四個步驟哪裡來的,所以只能背,筆者記憶不好,終歸是 “不算年輕了”。
所以除了死記硬背,還能怎麼辦呢?去實踐,然後理解,做過了的事情才印象深刻。

所以來看,如何實踐 & 理解:

先打開 Xcode 的 Scheme,然後在 Run 的選項下,選中Environment Variables,添加 Name 為DYLD_PRINT_STATISTICS,Value 為1。如下:

wecom20210803-103910.png

然後運行一次,會發現控制台中打印出了類似如下的信息:


Total pre-main time: 599.52 milliseconds (100.0%)
         dylib loading time: 101.25 milliseconds (16.8%)
        rebase/binding time:  55.26 milliseconds (9.2%)
            ObjC setup time: 189.95 milliseconds (31.6%)
           initializer time: 253.04 milliseconds (42.2%)
           slowest intializers :
             libSystem.B.dylib :   6.65 milliseconds (1.1%)
    libMainThreadChecker.dylib :  59.84 milliseconds (9.9%)
                       xxxTest : 313.12 milliseconds (52.2%)

這裡面的信息仔細對比:其中Total pre-main time指的是pre-main的總時間;

Total pre-main timedylib loading time + rebase/binding time + ObjC setup time + initializer time;

slowest intializers中的libMainThreadChecker,是因為 Scheme 中的Main Thread Checker
打開了,關閉即可,如下的地方勾選去除即可。

wecom20210809-101508.png

所以pre-main階段發生了什麼?就是發生了dylib loadingrebase/bindingObjC setup timeinitializer time。這樣就知道了這 4 個步驟的來歷,接下來再看看這幾個步驟都是做什麼的?

參考:https://devstreaming-cdn.apple.com/videos/wwdc/2016/406i3zbazbegkeh0udt/406/406_optimizing_app_startup_time.pdf?dl=1

wecom20210809-092908@2x.png

wecom20210809-092815@2x.png

wecom20210809-092553@2x.png

wecom20210809-093129@2x.png

wecom20210809-093951@2x.png

翻譯如下:

  • Total pre-main time指的是pre-main的總時間
    • 加載所有依賴的動態庫;
    • 修正DATA中的指針偏差;
    • 初始化所有對象。
  • dylib loading time
    • 加載 app 依賴的庫
    • 加載庫依賴的庫
  • rebase/binding time
    • rebasing: 調整鏡像的指針
    • binding: 設置指針到外部鏡像
  • ObjC setup time
    • 註冊 objc 類 (class registration);
    • Category 方法插入;
    • 保證每個 Selector 唯一;
  • initializer time
    • C++ 靜態對象初始化
    • objc 的+load方法加載
    • 執行main()

main 函數之後階段#

main 函數之後的優化,也要多注意,大家都知道application:didFinishLaunchingWithOptions:是啟動時初始化的方法,那這裡應該做些什麼?

首先問大家一個問題

啟動優化實踐#

application:didFinishLaunchingWithOptions:return YES之前寫一個 sleep (10);所以只要這個方法不返回,界面就會顯示LaunchScreen,即使已經初始化了首頁設置了 rootVC 也不會顯示。

面試相關#

+initialize、+init、+load 什麼時候調用、調用順序?

+initialize、+load 的區別?

+load 的加載是在 main 函數之前?還是之後?

參考#

Reducing Your App’s Launch Time
optimizing_app_startup_time
iOS 深思篇 | 啟動時間的度量和優化

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。