APP啟動過程及優(yōu)化

以下內(nèi)容僅僅作為向大佬們學習中的總結(jié)和記錄

一贾费、名詞解釋

1.什么是image
無論對于系統(tǒng)的動態(tài)鏈接庫還是對于App本身的可執(zhí)行文件而言,他們都算是image(鏡像),而每個App都是以image(鏡像)為單位進行加載的,image包括以下文件:
<1>executable可執(zhí)行文件 比如.o文件
<2>dylib 動態(tài)鏈接庫
<3>bundle 資源文件

2.什么是ImageLoader
image 表示一個二進制文件(可執(zhí)行文件或 so 文件)沥割,里面是被編譯過的符號耗啦、代碼等凿菩,而 ImageLoader 作用是將這些文件加載進內(nèi)存,且每一個文件對應一個ImageLoader實例來負責加載帜讲。

3.Mach-O指哪些文件
Mach是一個操作系統(tǒng)內(nèi)核衅谷,在Mach上,一種可執(zhí)行文件的格式是Mach-O似将。蘋果的大部分文件格式都是Mach-O格式获黔。在iOS中蚀苛,以下文件指的是Mach-O:
<1>Executable 可執(zhí)行文件
<2>Dylib 動態(tài)庫
<3>Bundle
<4>Image
<5>Framework

Mach-o結(jié)構(gòu)如圖:


image.png

可以通過命令行otool -l XXX來看看Mach-o內(nèi)部信息


image.png

Header頭部 ,包含可以執(zhí)行的CPU架構(gòu)玷氏, 比如Mac的 PPC, PPC64, IA-32, x86-64堵未,iOS的arm系列。
magic盏触,是mach-o文件的魔數(shù)渗蟹,0xfeedface代表的是32位,0xfeedfacf代表64位

cputype和cupsubtype代表的是cpu的類型和其子類型
filetype赞辩,文件類型
ncmds 指的是加載命令(load commands)的數(shù)量
sizeofcmds 表示load commands的總字節(jié)大小

Load commands 加載命令雌芽,包含文件的組織架構(gòu)和在虛擬內(nèi)存中的布局方式。
cmd 是load command的類型,LC_SEGMENT的含義是(將文件中的段映射到進程地址空間)
cmdsize 代表load command的大小
segname 16字節(jié)的段名字辨嗽,當前是__PAGEZERO
vmaddr 段的虛擬內(nèi)存起始地址
vmsize 段的虛擬內(nèi)存大小
.fileoff 段在文件中的偏移量
filesize 段在文件中的大小
maxprot世落,initprot 最高內(nèi)存保護和初始內(nèi)存保護
nsects段中包含section的數(shù)量


image.png

Data,可以擁有多個段(segment)糟需,每個段可以擁有零個或多個區(qū)域(section)屉佳。每一個段(segment)都擁有一段虛擬地址映射到進程的地址空間。大部分包含以下三個段:__TEXT 代碼段篮灼,只讀忘古,包括函數(shù),和只讀的字符串
__DATA 數(shù)據(jù)段诅诱,讀寫髓堪,包括可讀寫的全局變量等
__LINKEDIT 包含了方法和變量的元數(shù)據(jù)(位置,偏移量)娘荡,以及代碼簽名等信息干旁。
sectname 第一個是__text ,就是主程序代碼
segname 該section所屬的 segment名
addr 該section在內(nèi)存的啟始位置
size 該section的大小
offset 該section的文件偏移
align 字節(jié)大小對齊
reloff 重定位入口的文件偏移
nreloc 需要重定位的入口數(shù)量

二、啟動過程上

APP啟動分為熱啟動和冷啟動
啟動時間在小于400ms是最佳的炮沐,因為從點擊圖標到顯示Launch Screen争群,到Launch Screen消失這段時間是400ms。啟動時間不可以大于20s大年,否則會被系統(tǒng)殺掉换薄。

t(App總啟動時間) = t1(main()之前的加載時間) + t2(main()之后的加載時間)

t1 =自身App可執(zhí)行文件(.o文件的集合)的加載和系統(tǒng)dylib(動態(tài)鏈接庫)。動態(tài)鏈接庫包括:iOS 中用到的所有系統(tǒng) framework翔试,加載OC runtime方法的libobjc轻要,系統(tǒng)級別的libSystem,例如libdispatch(GCD)和libsystem_blocks (Block)垦缅。

具體加載順序是先加載可執(zhí)行文件冲泥,然后加載dyld,是個加載動態(tài)鏈接庫的庫。dyld從可執(zhí)行文件的依賴庫開始加載凡恍,遞歸加載所有的依賴庫

如何加載動態(tài)庫志秃?

在Xcode中,可以通過設置環(huán)境變量來查看App的啟動時間嚼酝,DYLD_PRINT_STATISTICS和DYLD_PRINT_STATISTICS_DETAILS

<1>load dylibs

dyld會首先讀取mach-o文件的Header和load commands浮还。 ?接著就知道了這個可執(zhí)行文件依賴的動態(tài)庫。例如加載動態(tài)庫A到內(nèi)存闽巩,接著檢查A所依賴的動態(tài)庫碑定,就這樣的遞歸加載,直到所有的動態(tài)庫加載完畢又官。通常一個App所依賴的動態(tài)庫在100-400個左右延刘,其中大多數(shù)都是系統(tǒng)的動態(tài)庫,它們會被緩存到dyld shared cache六敬,這樣讀取的效率會很高碘赖。

針對這一步驟的優(yōu)化有:
減少非系統(tǒng)庫的依賴
合并非系統(tǒng)庫
使用靜態(tài)資源,比如把代碼加入主程序

<2>Rebase&Bind

為什么要rebase外构?

有兩種主要的技術來保證應用的安全:ASLR和Code Sign普泡。

ASLR的全稱是Address space layout randomization,翻譯過來就是“地址空間布局隨機化”审编。App被啟動的時候撼班,程序會被映射到邏輯的地址空間(CPU的虛擬地址,從物理地址映射到虛擬地址)垒酬,這個邏輯的地址空間有一個起始地址砰嘁,而ASLR技術使得這個起始地址是隨機的。如果是固定的勘究,那么黑客很容易就可以由起始地址+偏移量找到函數(shù)的地址矮湘。

在進行Code sign的時候,加密不是針對于整個文件口糕,而是針對于每一個Page的缅阳。dyld進行加載的時候,是對每一個page進行獨立的驗證景描。

之所以要rebase是因為剛剛提到的ASLR使得地址隨機化十办,導致起始地址不固定,另外由于Code Sign超棺,導致不能直接修改Image向族。Rebase的時候只需要增加對應的偏移量即可。待Rebase的數(shù)據(jù)都存放在__LINKEDIT中说搅。

bind指向的是鏡像外部的資源指針炸枣。
rebase步驟先進行虏等,需要把鏡像讀入內(nèi)存弄唧,并以page為單位進行加密驗證适肠,保證不會被篡改,所以這一步的瓶頸在IO候引。bind在其后進行侯养,由于要查詢符號表,來指向跨鏡像的資源澄干,加上在rebase階段逛揩,鏡像已被讀入和加密驗證,所以這一步的瓶頸在于CPU計算麸俘。

優(yōu)化該階段的關鍵在于減少__DATA segment中的指針數(shù)量辩稽。我們可以優(yōu)化的點有:
減少Objc類數(shù)量, 減少selector數(shù)量
減少C++虛函數(shù)數(shù)量
轉(zhuǎn)而使用swift stuct(其實本質(zhì)上就是為了減少符號的數(shù)量)

Objc setup

Objective C是動態(tài)語言从媚,所以在執(zhí)行main函數(shù)之前逞泄,需要把類的信息注冊到一個全局的Table中。同時拜效,Objective C支持Category喷众,在初始化的時候,也會把Category中的方法注冊到對應的類中紧憾,同時會唯一Selector到千。

initializers

以上三步屬于靜態(tài)調(diào)整(fix-up),都是在修改__DATA segment中的內(nèi)容赴穗,而這里則開始動態(tài)調(diào)整憔四,開始在堆和棧中寫入內(nèi)容。 在這里的工作有:
Objc的+load()函數(shù)
C/C++靜態(tài)初始化對象和標記為attribute(constructor)的方法

總結(jié)一下:對于main()調(diào)用之前的耗時我們可以優(yōu)化的點有:
減少不必要的framework般眉,因為動態(tài)鏈接比較耗時
check framework應當設為optional和required加矛,如果該framework在當前App支持的所有iOS系統(tǒng)版本都存在,那么就設為required煤篙,否則就設為optional斟览,因為optional會有些額外的檢查
合并或者刪減一些OC類,關于清理項目中沒用到的類辑奈,使用工具AppCode代碼檢查功能苛茂,查到當前項目中沒有用到的類如下:
刪減一些無用的靜態(tài)變量
刪減沒有被調(diào)用到或者已經(jīng)廢棄的方法
將不必須在+load方法中做的事情延遲到+initialize中
盡量不要用C++虛函數(shù)(創(chuàng)建虛函數(shù)表有開銷)

三、啟動過程下

t2 = main方法執(zhí)行之后到AppDelegate類中的- (BOOL)Application:(UIApplication *)Application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法執(zhí)行結(jié)束前這段時間鸠窗。
主要是構(gòu)建第一個界面妓羊,并完成渲染展示。
大部分項目會在該方法里初始化第一個頁面稍计,那么第一個頁面的viewdidload時間就會算t2的時間中

大部分情況下我們都會把界面的初始化過程放在viewDidLoad躁绸,但是這個過程會影響消耗啟動的時間。特別是在類似TabBarController這種會嵌套childViewController的ViewController的情況,它也會把部分children也初始化净刮,因此各種viewDidLoad會遞歸的進行剥哑。

主要優(yōu)化方法
盡量減少初始頁面viewdidload方法中的業(yè)務

四、優(yōu)化總結(jié)

1.移除不需要的動態(tài)庫
2.移除不需要的類
一個叫做fui(Find Unused Imports)的開源項目能很好的分析出不再使用的類.https://github.com/dblock/fui
3.合并功能類似的類和擴展
由于Category和ObjC的動態(tài)綁定有很強的關系淹父,所以實際上分類是比較占用啟動時間的株婴。盡量合并一些分類,會對啟動有一定的優(yōu)化作用暑认。
4.壓縮圖片
5.優(yōu)化applicationdidfinishlaunching
6.優(yōu)化rootviewcontroller加載

參考文章
https://blog.csdn.net/Tencent_Bugly/article/details/77363817?locationNum=1&fps=1
https://blog.csdn.net/u011452278/article/details/54966682

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末困介,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蘸际,更是在濱河造成了極大的恐慌座哩,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粮彤,死亡現(xiàn)場離奇詭異八回,居然都是意外死亡,警方通過查閱死者的電腦和手機驾诈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門缠诅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人乍迄,你說我怎么就攤上這事管引。” “怎么了闯两?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵褥伴,是天一觀的道長。 經(jīng)常有香客問我漾狼,道長重慢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任逊躁,我火速辦了婚禮似踱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘稽煤。我一直安慰自己核芽,他們只是感情好,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布酵熙。 她就那樣靜靜地躺著轧简,像睡著了一般。 火紅的嫁衣襯著肌膚如雪匾二。 梳的紋絲不亂的頭發(fā)上哮独,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天拳芙,我揣著相機與錄音,去河邊找鬼皮璧。 笑死舟扎,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的恶导。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼浸须,長吁一口氣:“原來是場噩夢啊……” “哼惨寿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起删窒,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤裂垦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后肌索,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蕉拢,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年诚亚,在試婚紗的時候發(fā)現(xiàn)自己被綠了晕换。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡站宗,死狀恐怖闸准,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情梢灭,我是刑警寧澤夷家,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站敏释,受9級特大地震影響库快,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜钥顽,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一义屏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蜂大,春花似錦湿蛔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至财喳,卻和暖如春察迟,著一層夾襖步出監(jiān)牢的瞬間斩狱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工扎瓶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留所踊,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓概荷,卻偏偏與公主長得像秕岛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子误证,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

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

  • 1 dyld 1.1 dyld簡介 在iOS系統(tǒng)中继薛,幾乎所有的程序都會用到動態(tài)庫,而動態(tài)庫在加載的時候都需要用d...
    Kevin_Junbaozi閱讀 11,803評論 4 44
  • iOS 系統(tǒng)架構(gòu) Mac系統(tǒng)是基于Unix內(nèi)核的圖形化操作系統(tǒng)愈捅,Mac OS 和 iOS 系統(tǒng)架構(gòu)的對比分析發(fā)現(xiàn)遏考,...
    一個人在路上走下去閱讀 21,449評論 11 198
  • App 運行理論 理論速成Mach-O 術語Mach-O 是針對不同運行時可執(zhí)行文件的文件類型。文件類型:Exec...
    未明一二閱讀 542評論 1 3
  • 竟然是圖譜蓝谨,是我自己灌具,根據(jù)學過的知識整理出來的一種,方式譬巫,嗯咖楣,如果用簡書,一些芦昔,知名作者截歉,經(jīng)常舉的例子,花湯有點像...
    鄺鑒萍閱讀 498評論 0 4
  • 共讀班級:安徽省黃山市祁門縣祁山小學307班(小七班)領讀教師:程鳳女(繹心老師) 9月29日 讀書內(nèi)容:《穿越時...
    祁小繹心閱讀 475評論 0 2