iOS Dynamic Framework 對(duì)App啟動(dòng)時(shí)間影響實(shí)測(cè)

最近看到的Slow App Startup Times里提到:

The dynamic loader finds and reads the dependent dynamic libraries (dylibs) used by the App. Each library can itself have dependencies. The loading of Apple system frameworks is highly optimized but loading your embedded frameworks can be expensive. To speed up dylib loading Apple suggests you use fewer dylibs or consider merging them A suggested target is for six extra (non-system) frameworks.

至于什么是static lib什么是dynamic lib這里就不展開提了,大家可以通過(guò)在文章底部的相關(guān)鏈接去詳細(xì)了解苛骨。

引用一下官方的解釋就是:

  • A better approach is for an app to load code into its address space when it’s actually needed, either at launch time or at runtime. The type of library that provides this flexibility is called dynamic library.
  • When an app is launched, the app’s code—which includes the code of the static libraries it was linked with—is loaded into the app’s address space.Applications with large executables suffer from slow launch times and large memory footprints

如果給你一個(gè)簡(jiǎn)單的概念就是如果你的framework使用了swift就是dynamic lib悲幅。這也是本文要對(duì)比的主題:動(dòng)態(tài)的framework對(duì)app啟動(dòng)時(shí)間影響到底多大它呀。

測(cè)試的方法就采用 iOS 10 提供的新的環(huán)境變量 DYLD_PRINT_STATISTICS 輸出的app啟動(dòng)時(shí)間啊片。Xcode的版本是8.1骑脱,測(cè)試設(shè)備是iphone 6约计。cocoapod版本1.1。

注意疫向,測(cè)試過(guò)程發(fā)現(xiàn)每次獲得的時(shí)間統(tǒng)計(jì)都不一致,所以我這里的數(shù)據(jù)可能和你自己測(cè)試得到的不同豪嚎,但是我認(rèn)為這種偏差不影響定性搔驼。

基準(zhǔn)線:空的OC項(xiàng)目 VS 空的Swift項(xiàng)目

創(chuàng)建兩個(gè)沒有任何業(yè)務(wù)邏輯的空的項(xiàng)目。


純OC項(xiàng)目的啟動(dòng)時(shí)間
純swift空項(xiàng)目的啟動(dòng)時(shí)間

大概有10毫秒的差異侈询。這個(gè)差距考慮到測(cè)量的偏差可以認(rèn)為兩者幾乎是一致的舌涨。

但是有時(shí)會(huì)出現(xiàn)swift加載忽然提高到400ms的情況。這是因?yàn)橄到y(tǒng)的動(dòng)態(tài)framework只會(huì)加載一份扔字。假設(shè)10個(gè)app啟動(dòng)都用到了UIKit囊嘉,系統(tǒng)內(nèi)部也只加載了一份UIKit。所以有時(shí)swift項(xiàng)目啟動(dòng)的時(shí)候剛好用到了系統(tǒng)framework沒有緩存革为,就會(huì)顯得的長(zhǎng)一點(diǎn)扭粱。

6個(gè)framework

現(xiàn)在我們對(duì)比有代碼的情況。兩個(gè)項(xiàng)目分別加入5個(gè)依賴震檩。
這是OC項(xiàng)目的6個(gè)依賴:

  pod 'AFNetworking', '~> 3.0'
  pod 'Masonry'
  pod 'MJRefresh'
  pod 'SDWebImage'
  pod 'MBProgressHUD'
  pod 'IQKeyboardManager'

這是swift項(xiàng)目的6個(gè)依賴琢蛤,為了模擬真實(shí)生產(chǎn)中依然使用一些OC庫(kù)的情況,將3個(gè)庫(kù)換成了swift編碼的,保留了3個(gè)OC庫(kù):

  pod 'Alamofire'
  pod 'SnapKit'
  pod 'MJRefresh'
  pod 'Kingfisher'
  pod 'MBProgressHUD'
  pod 'IQKeyboardManager'

OC的啟動(dòng)時(shí)間在70-100ms左右虐块。這里取快的情況的數(shù)據(jù):


OC6個(gè)依賴的啟動(dòng)時(shí)間

swift項(xiàng)目在第一次安裝時(shí)的啟動(dòng)時(shí)間在dylib會(huì)多100ms俩滥,不知為何。swift項(xiàng)目在已經(jīng)安裝后運(yùn)行打開的成績(jī):


swift6個(gè)依賴

列一個(gè)橫向?qū)Ρ葓D:

結(jié)論

swift項(xiàng)目的dylib時(shí)間相比OC多了一百多毫秒贺奠,遠(yuǎn)遠(yuǎn)大于OC霜旧。

Swift 不使用framework VS 使用framework

我們猜測(cè)是不是加載framework導(dǎo)致時(shí)間增大很多呢。所以我們把這些依賴的代碼全部放在主app里儡率,不使用framework分離挂据。這次我們把幾個(gè)依賴的庫(kù)全部換成swift:

  pod 'Alamofire'
  pod 'SnapKit'
  pod 'Kingfisher'
  pod 'SwiftDate'
  pod 'ObjectMapper'

5個(gè)依賴的項(xiàng)目在app已經(jīng)安裝,運(yùn)行打開結(jié)果:


5個(gè)依賴

考慮到誤差可以認(rèn)為framework里的代碼是OC還是swift對(duì)于加載時(shí)間的影響并不大儿普。
把依賴的代碼全都合并到App里崎逃,就是采取手工拷貝的方式:

安裝后打開的啟動(dòng)時(shí)間統(tǒng)計(jì):



對(duì)比圖:


結(jié)論

如果把代碼收到拷貝進(jìn)app里,可以顯著降低dylib加載時(shí)間眉孩。

15個(gè)framework OC VS Swift

OC的podfile:

pod 'AFNetworking', '~> 3.0'
  pod 'Masonry'
  pod 'MJRefresh'
  pod 'SDWebImage'
  pod 'MBProgressHUD'
  pod 'IQKeyboardManager'

  pod 'FMDB'
  pod 'GPUImage'
  pod 'OpenUDID'
  pod 'DateTools'
  pod 'TMCache'
  pod 'WebViewJavascriptBridge'
  pod 'ZBarSDK'
  pod 'JSQMessagesViewController'
  pod 'YYKit'
  pod 'DZNEmptyDataSet'

swift項(xiàng)目的podfile:

pod 'AFNetworking', '~> 3.0'
  pod 'Alamofire'
  pod 'SnapKit'
  pod 'MJRefresh'
  pod 'Kingfisher'
  pod 'MBProgressHUD'
  pod 'IQKeyboardManager'

  pod 'FMDB'
  pod 'GPUImage'
  pod 'OpenUDID'
  pod 'SwiftDate'
  pod 'CryptoSwift'
  pod 'ObjectMapper'
  pod 'ZBarSDK'
  pod 'CocoaLumberjack/Swift'
  pod 'YYKit'
  pod 'DZNEmptyDataSet'

OC的結(jié)果:



swift的結(jié)果:


對(duì)比圖:


時(shí)間對(duì)比

縱向?qū)Ρ龋?/p>

結(jié)論

OC的項(xiàng)目隨著依賴增多个绍,初始化時(shí)間增大,但是dylib時(shí)間增加不明顯浪汪。swift則dylib時(shí)間大幅增加巴柿,初始化時(shí)間變化不大∷涝猓總的啟動(dòng)時(shí)間比OC多了200多毫秒广恢,隨著framework的增多,啟動(dòng)時(shí)間差距拉大呀潭。

25個(gè)dynamic framework

如果把dylib提高到25個(gè)時(shí)間又會(huì)增長(zhǎng)多少呢钉迷。
在15個(gè)基礎(chǔ)上再添加10個(gè)依賴:

  pod 'EZSwiftExtensions'
  pod 'ReactiveCocoa', '5.0.0-alpha.3'
  pod 'RxSwift',    '~> 3.0'
  pod 'RxCocoa',    '~> 3.0'
  pod 'MonkeyKing'
  pod 'Reusable'
  pod 'SwiftyJSON'
  pod 'XCGLogger'
  pod 'Gifu',    '~> 2.0.0-rc'
  pod 'Spring', :git => 'https://github.com/MengTo/Spring.git', :branch => 'swift3'

運(yùn)行時(shí)間:



和15個(gè)dylib的時(shí)候的對(duì)比:



dylib加載時(shí)間從400增加到600,增加了30%左右钠署。dylib數(shù)量從15到25個(gè)增加40%糠聪。接近線性。

總結(jié)

毫無(wú)疑問谐鼎,使用了dynamic framework后會(huì)增加app啟動(dòng)時(shí)間枷颊。如果你的數(shù)量在25個(gè)左右,相比OC的靜態(tài)framework啟動(dòng)時(shí)間會(huì)增加0.5s左右该面。我個(gè)人對(duì)于iOS提高加載framework的時(shí)間不太抱有希望,蘋果讓自定義的framework常駐內(nèi)存似乎也無(wú)望信卡,這個(gè)時(shí)間短期內(nèi)可能無(wú)法抹平隔缀。

如果人為的把一些外部依賴手動(dòng)管理在一個(gè)framework也是可行,但是如果復(fù)雜一點(diǎn)包的互相依賴的情況會(huì)比較費(fèi)心傍菇。

如果公司對(duì)性能有著苛刻要求可能500ms是難以忍受的猾瘸。但是我覺得對(duì)于大多數(shù)產(chǎn)品而言,犧牲這500ms的性能相比于使用OC,我覺得還是用OC比較難受牵触。

歡迎關(guān)注我的微博:@沒故事的卓同學(xué)


相關(guān)鏈接:
WWDC 2016 Session 406 Optimizing App Startup Time
What are Frameworks?
iOS 開發(fā)中的『庫(kù)』(一)
jverkoey/iOS-Framework

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末淮悼,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子揽思,更是在濱河造成了極大的恐慌袜腥,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钉汗,死亡現(xiàn)場(chǎng)離奇詭異羹令,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)损痰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門福侈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人卢未,你說(shuō)我怎么就攤上這事肪凛。” “怎么了辽社?”我有些...
    開封第一講書人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵伟墙,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我爹袁,道長(zhǎng)远荠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任失息,我火速辦了婚禮譬淳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘盹兢。我一直安慰自己邻梆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開白布绎秒。 她就那樣靜靜地躺著浦妄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪见芹。 梳的紋絲不亂的頭發(fā)上剂娄,一...
    開封第一講書人閱讀 49,079評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音玄呛,去河邊找鬼阅懦。 笑死,一個(gè)胖子當(dāng)著我的面吹牛徘铝,可吹牛的內(nèi)容都是我干的耳胎。 我是一名探鬼主播惯吕,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼怕午!你這毒婦竟也來(lái)了废登?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤郁惜,失蹤者是張志新(化名)和其女友劉穎堡距,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扳炬,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吏颖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了恨樟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片半醉。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖劝术,靈堂內(nèi)的尸體忽然破棺而出缩多,到底是詐尸還是另有隱情,我是刑警寧澤养晋,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布衬吆,位于F島的核電站,受9級(jí)特大地震影響绳泉,放射性物質(zhì)發(fā)生泄漏逊抡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一零酪、第九天 我趴在偏房一處隱蔽的房頂上張望冒嫡。 院中可真熱鬧,春花似錦四苇、人聲如沸孝凌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蟀架。三九已至,卻和暖如春榆骚,著一層夾襖步出監(jiān)牢的瞬間片拍,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工妓肢, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留穆碎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓职恳,卻偏偏與公主長(zhǎng)得像所禀,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子放钦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 二十二 福岡圓夢(mèng) 緣海終于還是要帶著藍(lán)去日本色徘,完成他們最浪漫、最偉大操禀、最難忘的婚禮褂策,從愛開始的這一座城市尋找他們的...
    易寫發(fā)閱讀 336評(píng)論 0 1
  • 美一個(gè)永恒的話題,美景颓屑,美食斤寂,美女。美可以成為任何事物的形容詞揪惦!我們每個(gè)人對(duì)美的定義也不盡相同遍搞! 就美女來(lái)講,不管...
    穗苗閱讀 206評(píng)論 0 0
  • 總是有人問我她怎么了器腋。她怎么不說(shuō)話溪猿,她怎么不出門,她怎么總躺著纫塌,她…… 我也不知道她怎么了诊县,她變得很沉悶,她不在呼...
    想和你回家閱讀 243評(píng)論 0 0
  • 不知何事縈懷抱措左, 醒也無(wú)聊依痊,醉也無(wú)聊, 夢(mèng)里何曾到謝橋怎披。 出自納蘭性德的《采桑子》胸嘁,包含了葉廣岑兩個(gè)中篇的名字。 ...
    小褶子乖乖閱讀 1,146評(píng)論 2 0