iOS【啟動優(yōu)化】

冷啟動 VS 熱啟動

04.png
05.png

如果你剛剛啟動過App献丑,這時候App的啟動所需要的數(shù)據(jù)仍然在緩存中,再次啟動的時候稱為熱啟動坝辫。如果設(shè)備剛剛重啟,然后啟動App射亏,這時候稱為冷啟動近忙。

啟動時間在小于400ms是最佳的,因為從點擊圖標到顯示Launch Screen智润,到Launch Screen消失這段時間是400ms及舍。啟動時間不可以大于20s,否則會被系統(tǒng)殺掉窟绷。

以main函數(shù)作為分水嶺锯玛,啟動時間其實包括了兩部分:main函數(shù)之前和main函數(shù)到第一個界面的viewDidAppear:。所以钾麸,優(yōu)化也是從兩個方面進行的更振,個人建議優(yōu)先優(yōu)化后者,因為絕大多數(shù)App的瓶頸在自己的代碼里饭尝。

Main函數(shù)之后

我們首先來分析下肯腕,從main函數(shù)開始執(zhí)行,到你的第一個界面顯示钥平,這期間一般會做哪些事情实撒。

*   執(zhí)行AppDelegate的代理方法,主要是didFinishLaunchingWithOptions
*   初始化Window涉瘾,初始化基礎(chǔ)的ViewController結(jié)構(gòu)(一般是UINavigationController+UITabViewController)
*   獲取數(shù)據(jù)(Local DB/Network)知态,展示給用戶。

AppDelegate

通常我們會在AppDelegate的代理方法里進行初始化工作立叛,主要包括了兩個方法:

didFinishLaunchingWithOptions
applicationDidBecomeActive
優(yōu)化這些初始化的核心思想就是:

能延遲初始化的盡量延遲初始化负敏,不能延遲初始化的盡量放到后臺初始化。

這些工作主要可以分為幾類:

三方SDK初始化秘蛇,比如Crash統(tǒng)計; 像分享之類的其做,可以等到第一次調(diào)用再出初始化。
初始化某些基礎(chǔ)服務(wù)赁还,比如WatchDog妖泄,遠程參數(shù)。
啟動相關(guān)日志艘策,日志往往涉及到DB操作蹈胡,一定要放到后臺去做
業(yè)務(wù)方初始化,這個交由每個業(yè)務(wù)自己去控制初始化時間朋蔫。

Main函數(shù)之前

Main函數(shù)之前是iOS系統(tǒng)的工作罚渐,所以這部分的優(yōu)化往往更具有通用性。

dylibs

在每個動態(tài)庫的加載過程中斑举, dyld需要:

1.  分析所依賴的動態(tài)庫
2.  找到動態(tài)庫的mach-o文件
3.  打開文件
4.  驗證文件
5.  在系統(tǒng)核心注冊文件簽名
6.  對動態(tài)庫的每一個segment調(diào)用mmap()
通常的搅轿,一個App需要加載很多個dylibs, 但是其中的系統(tǒng)庫被優(yōu)化富玷,可以很快的加載璧坟。應用所依賴的dylib文件可能會再依賴其他 dylib,所以dyld所需要加載的是動態(tài)庫列表一個遞歸依賴的集合赎懦。
針對這一步驟的優(yōu)化有:

1.  減少非系統(tǒng)庫的依賴
2.  合并非系統(tǒng)庫

啟動的第一步是加載動態(tài)庫雀鹃,加載系統(tǒng)的動態(tài)庫使很快的,因為可以緩存励两,而加載內(nèi)嵌的動態(tài)庫速度較慢黎茎。所以,提高這一步的效率的關(guān)鍵是:減少動態(tài)庫的數(shù)量当悔。

  • 合并動態(tài)庫傅瞻,比如公司內(nèi)部由私有Pod建立了如下動態(tài)庫:XXTableView, XXHUD, XXLabel踢代,強烈建議合并成一個XXUIKit來提高加載速度。

Rebase & Bind & Objective C Runtime

由于ASLR(address space layout randomization)的存在嗅骄,可執(zhí)行文件和動態(tài)鏈接庫在虛擬內(nèi)存中的加載地址每次啟動都不固定胳挎,所以需要這2步來修復鏡像中的資源指針,來指向正確的地址溺森。 rebase修復的是指向當前鏡像內(nèi)部的資源指針慕爬; 而bind指向的是鏡像外部的資源指針。
rebase步驟先進行屏积,需要把鏡像讀入內(nèi)存医窿,并以page為單位進行加密驗證,保證不會被篡改炊林,所以這一步的瓶頸在IO姥卢。bind在其后進行,由于要查詢符號表渣聚,來指向跨鏡像的資源隔显,加上在rebase階段,鏡像已被讀入和加密驗證饵逐,所以這一步的瓶頸在于CPU計算括眠。
優(yōu)化該階段的關(guān)鍵在于減少__DATA segment中的指針數(shù)量。我們可以優(yōu)化的點有:

1.  減少Objc類數(shù)量倍权, 減少selector數(shù)量
2.  減少C++虛函數(shù)數(shù)量

Rebase和Bind都是為了解決指針引用的問題掷豺。對于Objective C開發(fā)來說,主要的時間消耗在Class/Method的符號加載上薄声,所以常見的優(yōu)化方案是:

*   減少`__DATA`段中的指針數(shù)量当船。
*   合并Category和功能類似的類。比如:UIView+Frame,UIView+AutoLayout…合并為一個
*   刪除無用的方法和類默辨。
*   多用Swift Structs德频,因為Swfit Structs是靜態(tài)分發(fā)的。

Initializers

通常缩幸,我們會在+load方法中進行method-swizzling壹置,這也是Nshipster推薦的方式。

  • 用initialize替代load表谊。不少同學喜歡用method-swizzling來實現(xiàn)AOP去做日志統(tǒng)計等內(nèi)容钞护,強烈建議改為在initialize進行初始化。
  • 減少__atribute__((constructor))的使用爆办,而是在第一次訪問的時候才用dispatch_once等方式初始化难咕。
  • 不要創(chuàng)建線程
  • 使用Swfit重寫代碼。

pre-main階段耗時的影響因素:

動態(tài)庫加載越多,啟動越慢余佃。
ObjC類越多暮刃,函數(shù)越多,啟動越慢爆土。
可執(zhí)行文件越大啟動越慢沾歪。
C的constructor函數(shù)越多,啟動越慢雾消。
C++靜態(tài)對象越多,啟動越慢挫望。
ObjC的+load越多立润,啟動越慢。

整體上pre-main階段的優(yōu)化有:

①減少依賴不必要的庫媳板,不管是動態(tài)庫還是靜態(tài)庫桑腮;如果可以的話,把動態(tài)庫改造成靜態(tài)庫蛉幸;
如果必須依賴動態(tài)庫破讨,則把多個非系統(tǒng)的動態(tài)庫合并成一個動態(tài)庫;

②檢查下 framework應當設(shè)為optional和required奕纫,
如果該framework在當前App支持的所有iOS系統(tǒng)版本都存在提陶,那么就設(shè)為required,否則就設(shè)為optional匹层,
因為optional會有些額外的檢查隙笆;

③合并或者刪減一些OC類和函數(shù);
關(guān)于清理項目中沒用到的類升筏,使用工具AppCode代碼檢查功能撑柔,查到當前項目中沒有用到的類(也可以用根據(jù)linkmap文件來分析,但是準確度不算很高)您访;

④刪減一些無用的靜態(tài)變量铅忿,

⑤刪減沒有被調(diào)用到或者已經(jīng)廢棄的方法。

⑥將不必須在+load方法中做的事情延遲到+initialize中灵汪,盡量不要用C++虛函數(shù)(創(chuàng)建虛函數(shù)表有開銷)
因為load是在啟動的時候調(diào)用檀训,而initialize是在類首次被使用的時候調(diào)用,不過當你把load中的邏輯移到initialize中時候享言,一定要注意initialize的重復調(diào)用問題肢扯。

⑦類和方法名不要太長:iOS每個類和方法名都在__cstring段里都存了相應的字符串值,所以類和方法名的長短也是對可執(zhí)行文件大小是有影響的担锤;
因還是object-c的動態(tài)特性蔚晨,因為需要通過類/方法名反射找到這個類/方法進行調(diào)用,object-c對象模型會把類/方法名字符串都保存下來;

⑧用dispatch_once()代替所有的 attribute((constructor)) 函數(shù)铭腕、C++靜態(tài)對象初始化银择、ObjC的+load函數(shù);

⑨在設(shè)計師可接受的范圍內(nèi)壓縮圖片的大小累舷,會有意外收獲浩考。
壓縮圖片為什么能加快啟動速度呢?因為啟動的時候大大小小的圖片加載個十來二十個是很正常的被盈,
圖片小了析孽,IO操作量就小了,啟動當然就會快了只怎,比較靠譜的壓縮算法是TinyPNG袜瞬。

2、抽象重復代碼

1身堡、在iOS代碼中可能會為同一個類寫很多分類方法邓尤,由于參與開發(fā)同學較多,可能會導致方法重復贴谎,但是實際上運行起來只能有一個分類的方法被調(diào)用汞扎,這取決于哪個分類后被加載,然而編譯的二進制代碼中擅这,兩個方法應該是都存在的澈魄,這不僅會增加app體積,也會增加啟動時間仲翎,所以應該杜絕這樣的重復問題一忱;
2、有很多地方可能是名字不同谭确,但是函數(shù)的功能相同帘营,這個不容易被發(fā)現(xiàn),需要大家在寫代碼的過程中注意逐哈;
3芬迄、又或者兩個函數(shù)名字比較接近,里面有很多相似的代碼昂秃,這種情況下可以進行相同的代碼的提取禀梳。

main階段的優(yōu)化大致有如下幾個點:

①減少啟動初始化的流程,能懶加載的就懶加載肠骆,能放后臺初始化的就放后臺算途,
能夠延時初始化的就延時,不要卡主線程的啟動時間蚀腿,已經(jīng)下線的業(yè)務(wù)直接刪掉嘴瓤;
②優(yōu)化代碼邏輯扫外,去除一些非必要的邏輯和代碼,減少每個流程所消耗的時間廓脆;
③啟動階段使用多線程來進行初始化筛谚,把CPU的性能盡量發(fā)揮出來;
④使用純代碼而不是xib或者storyboard來進行UI框架的搭建停忿,尤其是主UI框架比如TabBarController這種驾讲,
盡量避免使用xib和storyboard,因為xib和storyboard也還是要解析成代碼來渲染頁面席赂,多了一些步驟吮铭;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市颅停,隨后出現(xiàn)的幾起案子谓晌,更是在濱河造成了極大的恐慌,老刑警劉巖便监,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異碳想,居然都是意外死亡烧董,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門胧奔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逊移,“玉大人,你說我怎么就攤上這事龙填「烊” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵岩遗,是天一觀的道長扇商。 經(jīng)常有香客問我,道長宿礁,這世上最難降的妖魔是什么案铺? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮梆靖,結(jié)果婚禮上控汉,老公的妹妹穿的比我還像新娘。我一直安慰自己返吻,他們只是感情好姑子,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著测僵,像睡著了一般街佑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天舆乔,我揣著相機與錄音岳服,去河邊找鬼。 笑死希俩,一個胖子當著我的面吹牛吊宋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播颜武,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼璃搜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了鳞上?” 一聲冷哼從身側(cè)響起这吻,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎篙议,沒想到半個月后唾糯,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡鬼贱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年移怯,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片这难。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡舟误,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出姻乓,到底是詐尸還是另有隱情嵌溢,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布蹋岩,位于F島的核電站赖草,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏剪个。R本人自食惡果不足惜疚顷,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望禁偎。 院中可真熱鬧腿堤,春花似錦、人聲如沸如暖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽盒至。三九已至酗洒,卻和暖如春士修,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背樱衷。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工棋嘲, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人矩桂。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓沸移,卻偏偏與公主長得像,于是被迫代替她去往敵國和親侄榴。 傳聞我的和親對象是個殘疾皇子雹锣,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348