冷啟動優(yōu)化

App啟動分為冷啟動和熱啟動,我們說的啟動優(yōu)化一般是指冷啟動優(yōu)化锹雏。若要想優(yōu)化巴比,首先我們必須明確啟動過程。

啟動過程分為兩個階段

  • main函數(shù)前
  • main函數(shù)后

main函數(shù)前

可以通過添加Xcode環(huán)境變量DYLD_PRINT_STATISTICS來打印pre-main花費的時間

如果想查看更加詳細的信息再添加環(huán)境變量DYLD_PRINT_STATISTICS_DETAILS

Total pre-main time: 5.0 seconds (100.0%)
         dylib loading time: 3.6 seconds (72.2%)
        rebase/binding time: 1.1 seconds (22.9%)
            ObjC setup time: 100.24 milliseconds (1.9%)
           initializer time: 139.23 milliseconds (2.7%)
           slowest intializers :
             libSystem.B.dylib :   5.24 milliseconds (0.1%)

執(zhí)行流程

啟動優(yōu)化.png
  1. 加載可執(zhí)行文件
  2. 加載動態(tài)庫由于使用了ASLRAdress Space Layout Randomizationrebase[調(diào)整鏡像內(nèi)指針偏移] binding[調(diào)整對鏡像外符號信用偏移]礁遵;一般來說動態(tài)庫會加載100-400個大多數(shù)為OS dylib(系統(tǒng)動態(tài)庫)轻绞,相對來說OS dylib在加載時做了優(yōu)化調(diào)整
  3. 初始化runtime:包括,類注冊榛丢,屬性動態(tài)調(diào)整铲球,方法唯一性驗證,分類中方法插入到類方法中
  4. C++靜態(tài)變量初始化晰赞,構造函數(shù)attribute(constructor)初始化

優(yōu)化方案

  1. 減少動態(tài)庫加載:蘋果支持6個非系統(tǒng)動態(tài)庫合并
合并動態(tài)庫:
lipo -create path/yourFramework1 path/yourFramework2 -output path/yourFramework

合并靜態(tài)庫:
lipo -create '/sim/lib.a' '/dev/lib.a' -output 'lib.a'
  1. 減少ObjC類(class)稼病,方法(selector),分類(category)的數(shù)量

    ObjC因為支持了動態(tài)語言掖鱼,內(nèi)部會維護一個記錄類名與類關系的表然走,如果類數(shù)量多就會造成表很大

    • 移除不用的類
    // 安裝fui工具,在終端中執(zhí)行命令 官網(wǎng):https://github.com/dblock/fui
    sudo gem install fui -n /usr/local/bin
    
    // 使用, 查找當前目錄下未使用的類;注意查找出的內(nèi)容并不一定靠譜戏挡,還需要自己在XCode中驗證
    fui find
    
    // 使用otool命令可查看__DATA.__objc_classrefs段和__DATA.__objc_classlist段芍瑞,兩者的差集可以認為是定義了但未使用的類。
    
    // 1. 獲取可執(zhí)行文件下所有OC類名
    otool -v -s __DATA __objc_classlist 可執(zhí)行文件名
    
    // 2. 獲取可執(zhí)行文件所有引用到的OC類名
    otool -v -s __DATA __objc_classrefs 可執(zhí)行文件名
    
    // 3. 兩者的差集就是代碼中沒有直接使用到的OC類褐墅,不過需要注意反射機制使用類名來操作的情況拆檬,需要人工做下篩選
    // 4. 獲取所有符號,可以取出地址與符號對應關系
    nm -nm 可執(zhí)行文件名
    
    // 5. 如果一個子類實例化妥凳,父類未實例化竟贯,那么父類不會出現(xiàn)在__objc_classrefs這個段里。需要將移除未使用的這部分OC類
    // 可以獲取到類的繼承關系
    otool -oV 可執(zhí)行文件名
    
    參考資料:https://juejin.im/post/5d5d1a92e51d45620923886a
    參考腳本:https://github.com/xuezhulian/classunref
    
  • 合并分類
  1. load方法中的內(nèi)容推遲到initialize中操作
放到initialize方法中逝钥,并適時使用dispatch_once來保證執(zhí)行效果
  1. 減少C++虛函數(shù)的數(shù)量
創(chuàng)建虛函數(shù)表有開銷屑那;
  1. 減少C/C++中構造器,非基本類型的常量
C/C++的構造器函數(shù)(用attriubte((constructor))修飾的函數(shù))艘款,和創(chuàng)建非基本類型的C++靜態(tài)全局變量(通常是類或結(jié)構體)
  1. 使用Swift struct
內(nèi)部做了優(yōu)化持际,符號數(shù)量更少
  1. 二進制重排,減少page fault產(chǎn)生

請求分頁系統(tǒng)中每當要訪問的頁面不存在是哗咆,便會觸發(fā)一個缺頁中斷(page fault)蜘欲,然后操作系統(tǒng)就會阻塞這個進程,晌柬,直到調(diào)頁完成后芒填,才會重新執(zhí)行呜叫。由此如果發(fā)生缺頁中斷次數(shù)太多就會耗時較多。我們此處只考慮啟動過程中

缺頁中斷視頻講解
https://www.bilibili.com/video/av86534144?p=6

重排的目的就是為了在啟動過程中盡可能少的觸發(fā)page fault殿衰。

查看當前App啟動產(chǎn)生多少次page fault.

1. 通過Profile -> System Trace
2. 選擇真機朱庆,選擇工程,點擊啟動闷祥,當首個頁面加載出來就停止
3. 選擇主線程娱颊,-> 選擇 Summary:Virtual Memory 其中File Backed Page In  Count 即為pageFault次數(shù)

方案:

1. 構建一個orderFile.order;有序文件
2. 在Xcode Build settings中搜索Order File凯砍,配置orderfile路徑
  • 構建有序文件

本質(zhì)是通過全局的AOP箱硕,Hook所有方法

使用AppOrderFiles工具進行操作
https://github.com/yulingtianxia/AppOrderFiles

詳細理解方案
http://www.zyiz.net/tech/detail-127196.html


main函數(shù)后

執(zhí)行流程

  1. 首屏初始化所需配置文件的讀寫操作
  2. 首屏列表數(shù)據(jù)的讀取
  3. 首屏渲染的大量計算等

優(yōu)化方案

梳理功能調(diào)整調(diào)用時機

a. 可以延遲加載的庫延遲
b. 復雜耗時計算,延遲或者開線程
c. 首頁控制器最好使用純代碼方式

常用策略

分析link map文件

link map是編譯連接時生成的一個txt文件悟衩,它生成的目的就是幫助程序員分析包大小剧罩。

link map記錄了每個方法在當前二進制架構下占據(jù)的空間。通過分析link map座泳,我們可以了解到每個類甚至每個方法占據(jù)了多少安裝包空間惠昔。

使用方式如下

// 1. 開啟
Xcode build setting 中開啟Write Link Map

// 2. 配置Linkmap路徑
path to link map

總結(jié)

大概闡述導致啟動慢的原因,及解決方案挑势;
針對比較深入的知識點镇防,也查看了不少資料,作為切入理解的點潮饱。作為后續(xù)深入研究的方向来氧。


參考及延伸:

http://www.reibang.com/p/b19cd03eea68
http://yulingtianxia.com/blog/2019/09/01/App-Order-Files/
http://www.zyiz.net/tech/detail-127196.html
https://developer.apple.com/library/archive/documentation/Performance/Conceptual/CodeFootprint/Articles/ImprovingLocality.html#//apple_ref/doc/uid/20001862-117091-BCIBJEBH

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市香拉,隨后出現(xiàn)的幾起案子啦扬,更是在濱河造成了極大的恐慌,老刑警劉巖凫碌,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扑毡,死亡現(xiàn)場離奇詭異,居然都是意外死亡证鸥,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進店門勤晚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來枉层,“玉大人,你說我怎么就攤上這事赐写∧窭” “怎么了?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵挺邀,是天一觀的道長揉忘。 經(jīng)常有香客問我跳座,道長,這世上最難降的妖魔是什么泣矛? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任疲眷,我火速辦了婚禮,結(jié)果婚禮上您朽,老公的妹妹穿的比我還像新娘狂丝。我一直安慰自己,他們只是感情好哗总,可當我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布几颜。 她就那樣靜靜地躺著,像睡著了一般讯屈。 火紅的嫁衣襯著肌膚如雪蛋哭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天涮母,我揣著相機與錄音谆趾,去河邊找鬼。 笑死哈蝇,一個胖子當著我的面吹牛棺妓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播炮赦,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼怜跑,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了吠勘?” 一聲冷哼從身側(cè)響起性芬,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎剧防,沒想到半個月后植锉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡峭拘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年俊庇,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鸡挠。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡辉饱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拣展,到底是詐尸還是另有隱情彭沼,我是刑警寧澤,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布备埃,位于F島的核電站姓惑,受9級特大地震影響褐奴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜于毙,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一敦冬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧望众,春花似錦匪补、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至甘耿,卻和暖如春踊兜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背佳恬。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工捏境, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人毁葱。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓垫言,卻偏偏與公主長得像,于是被迫代替她去往敵國和親倾剿。 傳聞我的和親對象是個殘疾皇子筷频,可洞房花燭夜當晚...
    茶點故事閱讀 44,652評論 2 354