iOS 啟動優(yōu)化篇

啟動速度

用戶從點擊APP圖標到完全看到APP內(nèi)容的過程稱為啟動难菌,如果啟動耗時較長可能會影響用戶的體驗,所以啟動速度優(yōu)化就顯得很有必要蔑滓。

  • 最佳速度:400ms郊酒,這是剛好是啟動動畫的時間遇绞,這是app啟動時間的最佳時間。業(yè)界建議啟動時間保持在1.5s內(nèi)比較合適燎窘。

  • 最慢速度:超過20s摹闽,則會被系統(tǒng)殺掉。

啟動的分類

1褐健、冷啟動:系統(tǒng)里沒有APP的進程緩存信息付鹿,例如重啟手機或者更新APP后的首次啟動APP,APP長時間不用系統(tǒng)清掉已有的進程緩存

2蚜迅、熱啟動:系統(tǒng)里有APP的進程緩存信息舵匾,例如殺死APP后短時間內(nèi)重啟APP

3、回前臺:APP退入后臺再進入前臺谁不,APP進程從掛起到激活狀態(tài)

一般只討論1坐梯、2兩種情況的啟動優(yōu)化。如何從代碼層面計算啟動速度刹帕?根據(jù)蘋果官方文檔的計算方式:進程創(chuàng)建時間到第一個CA::Transaction::commit()

啟動流程

image.png

1吵血、點擊APP圖標后,內(nèi)核創(chuàng)建APP進程

2轩拨、將APP的Mach-O可執(zhí)行文件mmap進虛擬內(nèi)存践瓷,加載dyld程序院喜,接下來調(diào)用_dyld_start函數(shù)開始程序的初始化

3亡蓉、重啟手機/更新APP會先創(chuàng)建啟動閉包,然后根據(jù)啟動閉包進行相關(guān)的初始化

4喷舀、將動態(tài)庫mmap進虛擬內(nèi)存砍濒,動態(tài)庫數(shù)量太多則這里耗時會增加

5、對動態(tài)庫和APP的Mach-O可執(zhí)行文件做bind&rebase硫麻,主要耗時在 Page In爸邢,影響 Page In 數(shù)量的是 objc 的元數(shù)據(jù)

6、初始化 objc 的 runtime拿愧,如果有了閉包杠河,由于閉包已經(jīng)初始化了大部分,這里只會注冊 sel 和裝載 category

7浇辜、+load 和靜態(tài)初始化被調(diào)用券敌,除了方法本身耗時,這里還會引起大量 Page In

8柳洋、初始化 UIApplication待诅,啟動 Main Runloop

9、執(zhí)行 will/didFinishLaunch熊镣,這里主要是業(yè)務代碼耗時

10卑雁、Layout募书,viewDidLoad 和 Layoutsubviews 會在這里調(diào)用,Autolayout 太多會影響這部分時間

11测蹲、Display莹捡,drawRect 會調(diào)用

12、Prepare弛房,圖片解碼發(fā)生在這一步

13道盏、Commit,首幀渲染數(shù)據(jù)打包發(fā)給 RenderServer文捶,啟動結(jié)束

什么是PageIn?
啟動的路徑上會觸發(fā)很多次 Page In荷逞,其實也比較容易理解,因為啟動的會讀寫二進制中的很多內(nèi)容粹排。Page In 會占去啟動耗時的很大一部分种远,我們來看看單個 Page In 的過程:

image.png

  • MMU 找到空閑的物理內(nèi)存頁面
  • 觸發(fā)磁盤 IO,把數(shù)據(jù)讀入物理內(nèi)存
  • 如果是 TEXT 段的頁顽耳,要進行解密
  • 對解密后的頁坠敷,進行簽名驗證 (iOS 13 對這個過程進行了優(yōu)化,Page In 的時候不需要解密了射富。)

啟動優(yōu)化

啟動速度優(yōu)化思路:

1膝迎、控制APP的可執(zhí)行文件大小

2、控制動態(tài)庫數(shù)量

3胰耗、控制Page In 次數(shù)

4限次、控制首幀渲染前業(yè)務邏輯相關(guān)耗時

5、控制首幀視圖渲染耗時柴灯,即上面流程中的步驟10-12

1卖漫、盡可能減少動態(tài)庫的引用

至于什么是動態(tài)庫,什么叫靜態(tài)庫赠群?
靜態(tài)庫:編譯時鏈接羊始,鏈接時完整地拷貝至可執(zhí)行文件中, 被多個依賴多次使用就會有多份冗余拷貝. 動態(tài)庫: 鏈接時不復制, 程序運行時由系統(tǒng)動態(tài)加載到內(nèi)存, 供程序調(diào)用, 系統(tǒng)只加載一次, 多個程序共用, 節(jié)省內(nèi)存. iOS 中的靜態(tài)庫與動態(tài)庫

2、刪除無用代碼

Q: 無用代碼會增加APP可執(zhí)行文件的大小嗎查描?
A: 項目工程中未使用到的無用代碼最終會編譯到APP的可執(zhí)行文件中區(qū)突委,所以會導致APP可執(zhí)行文件體積增加。當APP可執(zhí)行文件變大時冬三,會導致dyld加載可執(zhí)行文件的耗時增加匀油,即增加了啟動時間。

如何做长豁?

基于Mach-O可執(zhí)行文件格式中的字段來確定類或者函數(shù)是否被使用钧唐,優(yōu)點是實現(xiàn)簡單,缺點是不夠準確匠襟,只能做靜態(tài)分析钝侠,動態(tài)調(diào)用代碼無法查出來该园,所以刪代碼前需要二次確認,目前也有很多不錯的實現(xiàn)方案帅韧。

采用業(yè)界開源方案:WBBlades 分析項目中的無用類里初,該工具支持OC和Swift的檢測,且使用簡單忽舟。

3双妨、二進制重排

Q: 二進制重排為什么會加快啟動速度?
A: 當APP進程訪問一頁虛擬內(nèi)存page叮阅,而對應的物理內(nèi)存不存在時刁品,先觸發(fā)缺頁中斷(Page Fault)阻塞當前進程,然后加載數(shù)據(jù)到對應物理內(nèi)存(Release版本還要對加載的數(shù)據(jù)進行簽名)浩姥,所以缺頁中斷還是比較耗時的挑随。假設APP啟動時調(diào)用100個函數(shù),這100個函數(shù)如果分布在100個不同的內(nèi)存頁勒叠,那會產(chǎn)生100次缺頁中斷兜挨。如通過二進制重排將這100函數(shù)分布到50個或者更少的內(nèi)存頁中,缺頁中斷的次數(shù)減半眯分,啟動速度就提升了 拌汇。

獲取啟動階段Page Fault的次數(shù)
打開Instruments,選擇System Trace工具

image.png

重啟手機(熱啟動情況下系統(tǒng)已經(jīng)做了加載緩存弊决,產(chǎn)生缺頁中斷大幅減少噪舀,所以最好重啟手機),然后點擊啟動丢氢,待首屏出現(xiàn)后停止傅联,如下圖:
image.png

解決方案

獲取啟動階段調(diào)用的函數(shù)符號然后編寫order_file編譯順序文件然后在Build Settings -> Order File中配置一個后綴為order的文件路徑是實現(xiàn)二進制重排的核心思路先改。

使用clang編譯器靜態(tài)插樁
靜態(tài)插樁:在build settings->"Other C Flags"中添加"-fsanitize-coverage=func,trace-pc-guard"疚察。如過項目中有 Swift 代碼,還需要在 "Other Swift Flags"中加入"-sanitize-coverage=fun""-sanitize=undefined"仇奶,如下:

image.png

image.png

靜態(tài)插樁腳本 獲取啟動階段符號表的使用步驟:

1貌嫡、在Podfile中添加如下代碼:

pod 'YCSymbolTracker'
post_install do |installer|
    require './Pods/YCSymbolTracker/YCSymbolTracker/symbol_tracker.rb'
    symbol_tracker(installer)
end

然后執(zhí)行pod install

2、再首幀完成渲染前調(diào)用如下代碼:

    // 首幀渲染完成后調(diào)用此方法该溯,一般在跟控制器的viewDidAppear方法中調(diào)用即可
    static func runAfterFirstFrameRendered(){
        ....省略的業(yè)務代碼
        
        // 首幀渲染前調(diào)用監(jiān)控代碼
        let filePath = NSTemporaryDirectory().appending("/demo.order")
        YCSymbolTracker.exportSymbols(filePath: filePath)
    }

3岛抄、關(guān)機然后打開APP,獲取啟動階段的符號表


image.png
4狈茉、首幀渲染前的業(yè)務邏輯優(yōu)化

這部分代表了main()函數(shù)之后的時間夫椭,即從didFinishLaunchingWithOptions()開始到根控制器viewDidAppear函數(shù)結(jié)束主線程耗時的優(yōu)化

解決方案:

利用Xcode自帶的Instruments工具APP Launch分析啟動耗時,找出耗時嚴重的函數(shù)調(diào)用然后進行優(yōu)化氯庆。該工具會追蹤應用啟動后5秒內(nèi)的所有線程的耗時蹭秋,自帶Time Profiler和應用進程的System Trace兩個看板扰付,如下:


image.png

接下來利用System Trace功能對APP啟動后的業(yè)務邏輯進行耗時分析,點擊System Trace看板(也就是上面FilmoraGo)左邊的右箭頭仁讨,選擇Main Thread羽莺,接下來就可以看到啟動階段各個函數(shù)的耗時了。



這里分析比如我們可以把一些類似加載字體洞豁,或者一些不影響業(yè)務的操作延后或者放到子線程中執(zhí)行盐固。

參考文章

抖音品質(zhì)建設 - iOS啟動優(yōu)化《原理篇》

抖音品質(zhì)建設 - iOS啟動優(yōu)化《實戰(zhàn)篇》

基于mach-o+反匯編的無用類檢測

iOS靜態(tài)庫&動態(tài)庫依賴探索

IOS優(yōu)化篇之啟動速度優(yōu)化(一)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市丈挟,隨后出現(xiàn)的幾起案子刁卜,更是在濱河造成了極大的恐慌,老刑警劉巖曙咽,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件长酗,死亡現(xiàn)場離奇詭異,居然都是意外死亡桐绒,警方通過查閱死者的電腦和手機夺脾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來茉继,“玉大人咧叭,你說我怎么就攤上這事∷附撸” “怎么了菲茬?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長派撕。 經(jīng)常有香客問我婉弹,道長,這世上最難降的妖魔是什么终吼? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任镀赌,我火速辦了婚禮,結(jié)果婚禮上际跪,老公的妹妹穿的比我還像新娘商佛。我一直安慰自己,他們只是感情好姆打,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布良姆。 她就那樣靜靜地躺著,像睡著了一般幔戏。 火紅的嫁衣襯著肌膚如雪玛追。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天闲延,我揣著相機與錄音痊剖,去河邊找鬼伯复。 笑死,一個胖子當著我的面吹牛邢笙,可吹牛的內(nèi)容都是我干的啸如。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼氮惯,長吁一口氣:“原來是場噩夢啊……” “哼叮雳!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起妇汗,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤帘不,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后杨箭,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寞焙,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年互婿,在試婚紗的時候發(fā)現(xiàn)自己被綠了捣郊。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡慈参,死狀恐怖呛牲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情驮配,我是刑警寧澤娘扩,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站壮锻,受9級特大地震影響稠茂,放射性物質(zhì)發(fā)生泄漏惊完。R本人自食惡果不足惜厢汹,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一霹俺、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧途事,春花似錦验懊、人聲如沸擅羞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽减俏。三九已至召烂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間娃承,已是汗流浹背奏夫。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工怕篷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人酗昼。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓廊谓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親麻削。 傳聞我的和親對象是個殘疾皇子蒸痹,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

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