App啟動優(yōu)化

一击碗、冷啟動和熱啟動
  • 定義:
    • 1.關(guān)于冷啟動:業(yè)界對冷啟動的定義沒有問題,普遍認為是手機開機后第一次啟動某個APP李茫。
    • 2.關(guān)于熱啟動:
      對熱啟動有兩種不同的看法:
      • 1.有些人認為是按下home鍵把APP掛到后臺菠劝,之后點擊APP的icon再拉回來到前臺算是熱啟動;
      • 2.也有些人認為是手機開機后在短時間內(nèi)第二次啟動APP(殺掉進程重啟)算是熱啟動(此時dyld會對部分APP的數(shù)據(jù)和庫進行緩存派任,所以比第一次啟動要快)。

(一般認為APP從后臺拉起到前臺的時間沒啥研究的意義璧南,所以在統(tǒng)計啟動時間時掌逛,會傾向于后一種說法,不過具體怎么定義看個人司倚,知道其中的區(qū)別就好)

如果啟動過豆混,內(nèi)存頁就已經(jīng)加載進內(nèi)存了,內(nèi)存頁如果要銷毀只能是被覆蓋动知,所以這時候的加載進物理內(nèi)存的時候皿伺,實際內(nèi)存中已經(jīng)存在值,所以啟動就會變快盒粮。

二心傀、優(yōu)化的方向

1.減少流程的數(shù)量。
2.減少每個流程的消耗拆讯。

三脂男、APP的啟動過程
四、啟動時間分布

在Xcode中种呐,可以通過設(shè)置環(huán)境變量來查看App的啟動時間宰翅,DYLD_PRINT_STATISTICSDYLD_PRINT_STATISTICS_DETAILS


根據(jù)xcode打印可以看到:
動態(tài)庫的加載

  • rebase/binding

    • 方法爽室、類汁讼、Category這些需要rebase和 binding
    • binding
      Mach-O _DATA建立指針,指向外部函數(shù)阔墩,我們編譯的時候嘿架,共享緩存庫里邊的代碼指向的就是這里,鏈接的時候啸箫,通過dyld指向外部具體真實的地址耸彪。PIC技術(shù)
      fishook就是利用這個中轉(zhuǎn),hook的系統(tǒng)c函數(shù)忘苛。
  • Objc setup

    • 類的初始化過程在這里邊
      ①讀取二進制文件的 DATA 段內(nèi)容蝉娜,找到與 objc 相關(guān)的信息
      ②注冊 Objc 類,ObjC Runtime 需要維護一張映射類名與類的全局表扎唾。當加載一個 dylib 時召川,其定義的所有的類都需要被注冊到這個全局表中;
      ③讀取 protocol 以及 category 的信息胸遇,把category的定義插入方法列表 (category registration)荧呐,
      ④確保 selector 的唯一性
  • initializer
    load等函數(shù),C++的構(gòu)造函數(shù)

耗時比較多的
加載自己的庫可能比較耗時

兩個階段分別是 pre- main 和 main啟動到viewDidAppear:



pre-main過程:



什么是dyld?
dyld是一個專門用來加載動態(tài)鏈接庫的庫纸镊。

執(zhí)行從dyld開始倍阐,dyld從可執(zhí)行文件的依賴開始, 遞歸加載所有的依賴動態(tài)鏈接庫。

五薄腻、 Dyld加載過程

加載Mach-O文件收捣,加載一塊比較大的內(nèi)存空間,地址重定向
啟動dyld的main函數(shù)

  • 配置xcode的環(huán)境變量 (arguments)
  • 加載共享緩存庫庵楷,UIKit 和 Foundation這些

加載LoadCommons段一系列加載
加載動態(tài)庫罢艾,包括自己的和系統(tǒng)的,實例化主程序的imageLoader尽纽,添加進imageList
鏈接主程序

開始初始化主程序
*runtime配合加載咐蚯,runtime加載loadImages方法,這個方法就是prepare_load_methods(mh)
*加載load和C++構(gòu)造函數(shù)
找main函數(shù)

配置(環(huán)境變量) — 加載(共享動態(tài)庫弄贿,主程序春锋,動態(tài)庫) — 鏈接(鏈接主程序,動態(tài)庫) — 初始化(程序)

  • 加載動態(tài)庫過程差凹,動態(tài)鏈接器dyld需要做如下操作
    1.分析依賴的動態(tài)庫
    2.找到動態(tài)庫的Mach-O文件
    3.打開文件
    4.驗證文件
    5.在系統(tǒng)的內(nèi)核注冊文件簽名
    6.對動態(tài)庫的每個segment調(diào)用mmap()

針對這一步優(yōu)化

1.減少非系統(tǒng)的動態(tài)庫
2.使用靜態(tài)庫而不是動態(tài)庫
3.合并非系統(tǒng)的動態(tài)庫為一個

1.動態(tài)庫盡可能少期奔,不要多與6個侧馅,如果多了,盡可能合并
2.20000個類 800毫秒
3.swift靜態(tài)語言呐萌,性能更高

六馁痴、ObjC SetUp

由于之前2步驟的優(yōu)化,這一步實際上沒有什么可做的肺孤。幾乎都靠 Rebasing 和 Binding 步驟中減少所需 fix-up 內(nèi)容罗晕。因為前面的工作也會使得這步耗時減少。

七赠堵、Initializers
  • 以上三步屬于靜態(tài)調(diào)整小渊,都是在修改__DATA segment中的內(nèi)容
    現(xiàn)在開始動態(tài)調(diào)整,在堆和棧中寫入內(nèi)容茫叭。 工作主要有:
    1酬屉、Objc+load()函數(shù)
    2、C++的構(gòu)造函數(shù)屬性函數(shù) 形如attribute((constructor)) void DoSomeInitializationWork()
    3杂靶、非基本類型的C++靜態(tài)全局變量的創(chuàng)建(通常是類或結(jié)構(gòu)體)(non-trivial initializer) 比如一個全局靜態(tài)結(jié)構(gòu)體的構(gòu)建梆惯,如果在構(gòu)造函數(shù)中有繁重的工作,那么會拖慢啟動速度
    可以做的優(yōu)化有:
    ①使用 +initialize 來替代 +load
    ②不要使用 atribute((constructor)) 將方法顯式標記為初始化器吗垮,而是讓初始化方法調(diào)用時才執(zhí)行垛吗。 比如使用 dispatch_once(),pthread_once() 或 std::once()。也就是在第一次使用時才初始化烁登,推遲了一部分工作耗時怯屉。 也盡量不要用到C++的靜態(tài)對象。

從效率上來說饵沧,在+load+initialize里執(zhí)行同樣的代碼锨络,效率是一樣的,即使有差距狼牺,也不會差距太大羡儿。 但所有的+load方法都在啟動的時候調(diào)用,方法多了就會嚴重影響啟動速度了是钥。 就說我們項目中掠归,有200個左右+load方法,一共耗時大概1s 左右悄泥,這塊就會嚴重影響到用戶感知了虏冻。 而+initialize方法是在對應(yīng) Class 第一次使用的時候調(diào)用,這是一個懶加載的方法弹囚,理想情況下厨相,這200個+load方法都使用+initialize來代替,將耗時分攤到用戶使用過程中,每個方法平均耗時只有5ms蛮穿,用戶完全可以無感知庶骄。

八、二進制重排

iOS的虛擬內(nèi)存和物理內(nèi)存:



之前所有應(yīng)用都加載進內(nèi)存條中践磅,會有安全問題瓢姻,會訪問到其他人的軟件中去

iOS虛擬內(nèi)存有4G的

CPU通過 操作系統(tǒng)映射表 映射虛擬內(nèi)存和物理真實內(nèi)存
也就是我們訪問虛擬內(nèi)存,都會走到映射表音诈,然后映射到真實的物理內(nèi)存。(每個映虛擬內(nèi)存對應(yīng)一個映射表)

(mmp)分頁加載绎狭,提高內(nèi)存的利用率

內(nèi)存是以字節(jié)為單位细溅,內(nèi)存以頁管理 PAGE,Linux每1頁4KB儡嘶,iOS每一頁16KB

用這種分頁加載喇聊,用到哪塊內(nèi)存就加載到真實內(nèi)存
上述P2加載的時候,發(fā)現(xiàn)真實內(nèi)存沒有蹦狂,缺頁誓篱,CPU會臨時加載

如果啟動的時候缺頁比較多(缺頁異常),就會不斷去映射到物理內(nèi)存凯楔,就會卡頓
iOS的內(nèi)存地址窜骄,與編譯順序有關(guān),所以如果方法在不同的類摆屯,類的加載差距比較大邻遏,那么就會加載比較多的頁,就會浪費時間虐骑。
iOS系統(tǒng)還會對加載的每一頁做簽名認證准验,所以更加消耗時間。

system trace
Main Thread
Virtual Memory File Backard Page In

ldyd
order_file 自己寫一個文件廷没,里邊指定方法的順序糊饱,可以將啟動要調(diào)用的方法,都放到里邊颠黎。
libc-order在objc源碼里邊另锋,這就是二進制重排

所有OC方法獲取
用fishhook 去 HOOK objc_msgSend()方法,可以拿到所有的函數(shù)
可以用Clang插庒的方式AOP

八盏缤、main過程:
  • Main函數(shù)之后

1.懶加載
2.發(fā)揮CPU的價值砰蠢,用多線程的方式。
3.框架的搭建盡量避免stroyboard 和 xib

  • 分階段加載:

  • 在didFinishLunch中啟動的:

    • 埋點功能唉铜、
    • Crash 采集
    • 網(wǎng)絡(luò)配置等
  • 在首頁viewDidappear

    • 初始化SDK台舱,友盟SDK、人臉識別SDK后移
    • 開始定位(顯示定位中),定位可以緩存竞惋,先加載柜去,定位同步進行,如果緩存的地理位置不一樣拆宛,然后才更新
    • 配置下發(fā)等
  • 多線程啟動

嘗試使用多線程啟動
將數(shù)據(jù)庫的配置嗓奢、SDwebimage UA的配置放到子線程中初始化,引入狀態(tài)管理浑厚,需要監(jiān)控子線程任務(wù)狀態(tài)股耽,判斷是否取消假的開屏頁面。

廣告同步加載钳幅,2秒回來了就展示物蝙,不回來就過
Timer Profile的使用

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市敢艰,隨后出現(xiàn)的幾起案子诬乞,更是在濱河造成了極大的恐慌,老刑警劉巖钠导,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件震嫉,死亡現(xiàn)場離奇詭異,居然都是意外死亡牡属,警方通過查閱死者的電腦和手機票堵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來湃望,“玉大人换衬,你說我怎么就攤上這事≈ぐ牛” “怎么了瞳浦?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長废士。 經(jīng)常有香客問我叫潦,道長,這世上最難降的妖魔是什么官硝? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任矗蕊,我火速辦了婚禮,結(jié)果婚禮上氢架,老公的妹妹穿的比我還像新娘傻咖。我一直安慰自己,他們只是感情好岖研,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布卿操。 她就那樣靜靜地躺著警检,像睡著了一般。 火紅的嫁衣襯著肌膚如雪害淤。 梳的紋絲不亂的頭發(fā)上扇雕,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機與錄音窥摄,去河邊找鬼镶奉。 笑死,一個胖子當著我的面吹牛崭放,可吹牛的內(nèi)容都是我干的哨苛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼币砂,長吁一口氣:“原來是場噩夢啊……” “哼移国!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起道伟,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎使碾,沒想到半個月后蜜徽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡票摇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年拘鞋,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片矢门。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡盆色,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出祟剔,到底是詐尸還是另有隱情隔躲,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布物延,位于F島的核電站宣旱,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏叛薯。R本人自食惡果不足惜浑吟,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望耗溜。 院中可真熱鬧组力,春花似錦、人聲如沸抖拴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至轩触,卻和暖如春寞酿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背脱柱。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工伐弹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人榨为。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓惨好,卻偏偏與公主長得像,于是被迫代替她去往敵國和親随闺。 傳聞我的和親對象是個殘疾皇子日川,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

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

  • 背景 一個項目做的時間長了,啟動流程往往容易雜亂矩乐,庫也用的越來越多龄句,APP的啟動時間也會慢慢變長。本次將針對iOS...
    lp_lp閱讀 1,565評論 0 12
  • 通過閱讀這篇文章散罕,我們將了解APP啟動過程中都做了哪些事情分歇。文章分為三部分,第一部分是原理講解欧漱,第二部分是優(yōu)化方案...
    CNWH閱讀 907評論 0 4
  • App的啟動可以分為2種: 冷啟動(Cold Launch)從零開始啟動APP 熱啟動(Warm Launch)A...
    Arthur澪閱讀 703評論 0 0
  • 場景 假設(shè)一個這樣的場景职抡,早高峰趕公交,沒帶公交卡误甚,掏出手機打開App1準備掃碼上車缚甩,結(jié)果App半天進不去,后面的...
    寒江飄雪閱讀 440評論 1 4
  • 1.App啟動過程 解析Info.plist加載相關(guān)信息窑邦,例如如閃屏沙箱建立擅威、權(quán)限檢查 Mach-O加載如果是胖二...
    音符上的碼字員閱讀 1,305評論 0 4