iOS啓動優化之Static linking vs Dyld 3

原文地址緩存

Static linking

咱們在iOS啓動優化之從exec()到main()這篇文章中介紹過,動態連接器在搜索依賴項時進行大量的計算和磁盤IO。安全

靜態連接消除了全部dylib搜索的須要-依賴和可執行文件成爲一體。閉包

所以,能夠將一些庫靜態地連接到主可執行文件中,減小framework的數量,從而達到優化應用程序啓動時間的目的。架構

那麼如何將framework編譯爲靜態庫呢?ide

在Xcode9中,能夠經過Build Settings中的MACH_O_TYPE = staticlib來設置,當設置該標誌時,連接器會生成靜態庫。至於經過cocoapods集成的庫,咱們必須在podfile中建立一個自定義腳本,以便僅在pod安裝期間(即依賴項安裝期間)爲選定的外部庫設置此標誌,由於cocoapods在每次從新安裝時都會爲託管庫建立新的工程結構。函數

若是想在Xcode9以前執行靜態連接,可使用libtool測試

除了動態庫,framework中還可能包含資源(圖像、nib等)。咱們去掉了動態庫,可是不能留下只包含資源的framework。資源包(bundle)是蘋果生態系統中包裝資源的一種標準方式,能夠經過腳本,將framework中的全部資源輸出到*.bundle中。而後,經過代碼讓應用程序能自動使用正確的資源位置。優化

下面咱們來看下,通過靜態連接處理以後,啓動時間有什麼變化?ui

下面這張圖顯示了在不一樣設備上,將26個dylibs進行靜態連接處理以後,啓動時間的變化。3d

能夠看到在iPhone 5C上的啓動時間減小約2秒。在iPad 2上,啓動時間獲得了更大的改善——相差約4.5秒。

注意:若是有多個靜態連接庫,注意不要將其與多個動態庫連接-這將致使靜態庫對象在不一樣的動態庫中重複,這多是一個嚴重的問題。

Dyld 3

在 iOS 13 以前,全部的第三方 App 都是經過 Dyld 2 來啓動 App 的,其加載過程在iOS啓動優化之從exec()到main()這篇文章中也介紹過,這裏就不在贅述。

Dyld 2加載過程當中,會進行大量的計算和I/O操做,所以,會致使 App 啓動時間加長。因此蘋果開發團隊爲了加快啓動速度,在 WWDC2017上正式提出了 Dyld 3。

Dyld 3 被分爲了三個組件:

  • 一個進程外的 MachO 解析器。
    • 預先處理了全部可能影響啓動速度的 search path、@rpaths 和環境變量。
    • 而後分析 Mach-O 的 Header 和依賴,並完成了全部符號查找的工做。
    • 最後將這些結果建立成了一個啓動閉包。
    • 這是一個普通的 daemon 進程,可使用一般的測試架構。
  • 一個進程內的引擎,用來運行啓動閉包。
    • 這部分在進程中處理。
    • 驗證啓動閉包的安全性,而後映射到 dylib 之中,再跳轉到 main 函數。
    • 不須要解析 Mach-O 的 Header 和依賴,也不須要符號查找。
  • 一個啓動閉包緩存服務。
    • 系統 App 的啓動閉包被構建在一個 Shared Cache 中, 咱們甚至不須要打開一個單獨的文件。
    • 對於第三方的 App,咱們會在 App 安裝或者升級的時候構建這個啓動閉包。
    • 在 iOS、tvOS、watchOS中,這這一切都是 App 啓動以前完成的。在 macOS 上,因爲有 Side Load App,進程內引擎會在首次啓動的時候啓動一個 daemon 進程,以後就可使用啓動閉包啓動了。

Dyld 3 把不少耗時的查找、計算和 I/O 操做都預先處理好了,使得啓動速度有了很大的提高。

經過測試,Dyld 2 和 Dyld 3啓動時間的對比:

launch type Dyld 2 Dyld 3
warm 0.722s 0.731s
cold 3.687s 2.947s

能夠看出,在冷啓動時Dyld3 比 Dyld2快20%

Static linking VS Dyld 3

測試結果以下:

launch type Dyld 3 static
warm 0.731s 0.679s
cold 2.947s 2.276s

經過測試結果,咱們能夠看出,使用靜態連接的 App 比Dyld 3的App啓動的更快。


掃一掃關注咱們,get更多iOS技能

相關文章
相關標籤/搜索