美團(tuán)iOS啟動分析與對比

背景

冷啟動時長是App性能的重要指標(biāo)榆骚,作為用戶體驗的第一道“門”晶框,直接決定著用戶對App的第一印象吉执。 招聘客戶端App都對啟動時長或多或少都進(jìn)行過一些優(yōu)化挺益,但相對于主流App啟動時長差了不少涕蚤,仍然有較大的優(yōu)化空間宪卿。

方向

本次啟動專項分析從兩個方向重點進(jìn)行分析:
一、美團(tuán)啟動分析(美團(tuán)App啟動為什么快万栅?)
二佑钾、招才貓啟動分析(我們App啟動為什么比美團(tuán)慢?)
三烦粒、后續(xù)規(guī)劃

定義

冷啟動定義

雖然冷iOS啟動有:開機(jī)啟動App(完全冷啟動)和短時間內(nèi)再次啟動App(溫啟動)兩種休溶,但對于啟動流程和將要做的啟動優(yōu)化來說并無區(qū)別代赁。一般而言,可以把iOS冷啟動的過程定義為:從用戶點擊App圖標(biāo)開始到第一個頁面展示為止兽掰。

啟動過程階段定義

啟動過程可以分為三個階段進(jìn)行分析:
T1:main函數(shù)之前芭碍,系統(tǒng)會進(jìn)行加載動態(tài)庫、注冊O(shè)bjc類等系統(tǒng)操作
T2:main函數(shù)到didFinishLaunching方法執(zhí)行完成期間會進(jìn)行SDK初始化等操作
T3:didFinishLaunching執(zhí)行完成到首頁面展示期間會進(jìn)行頁面的創(chuàng)建和渲染工作


美團(tuán)App啟動分析

一孽尽、如何統(tǒng)計第三方App

關(guān)于如何統(tǒng)計競品或者主流App的啟動耗時情況窖壕,市面上包含知乎團(tuán)隊采用的方案是進(jìn)行屏幕錄制+腳本,分析視頻圖像相似度的關(guān)鍵時間節(jié)點杉女。此方案弊端較多瞻讽,這里以逆向分析的方向提供兩種統(tǒng)計方案:

  • Theos+Tweak 越獄開發(fā)工具包,可注入代碼到正版App中
  • Frida+Monkey 砸殼重裝熏挎,注入代碼重新安裝App且可進(jìn)行- Debug調(diào)試

此次分析采用的是Frida+Monkey的方式速勇,最終都會將注入代碼以.dylib的方式注入到App中, 新注入的dylib庫會增加一定的耗時坎拐,需要忽略掉烦磁。

  libmeituanDylib.p :  34.00 milliseconds (1.6%)  // 忽略
  imeituan : 107.84 milliseconds (5.0%)



二、準(zhǔn)備注入的代碼

將App啟動過程中T2哼勇、T3階段關(guān)鍵時間節(jié)點方法進(jìn)行hook:

  • 1都伪、利用sysctl函數(shù)獲取進(jìn)程創(chuàng)建時間
  • 2、利用切面Hook猴蹂,對系統(tǒng)方法 didFinishLaunchingWithOptions 的開始和結(jié)束調(diào)用進(jìn)行打點
  • 3院溺、利用MoneyDev中的Logos語法,找到首頁的Controller磅轻,對viewDidAppear方法進(jìn)行hook打點珍逸。 (ps:如果直接對UIViewController的viewDidAppear進(jìn)行hook,拿到的時長一般都是TabBarVC聋溜、NavigationVC顯示的時長)

美團(tuán)首頁頁面結(jié)構(gòu):
圖片2.png

打點:

%hook MBCContainerViewController
- (void)viewDidAppear:(BOOL)animated {
   %orig;
   // 打點
}
%end





三谆膳、美團(tuán)App啟動階段時長分析
T1階段耗時分析

添加Xcode配置 DYLD_PRINT_STATISTICS_DETAILS 得出 pre-main 階段耗時
image.png

以美團(tuán)為標(biāo)準(zhǔn),招才貓的pre-main耗時比美團(tuán)多350ms:

  • dylib loading time: 動態(tài)庫加載時長撮躁,經(jīng)過分析美團(tuán)的動態(tài)庫數(shù)量為148個漱病,招才貓為73個,耗時相差85ms把曼,轉(zhuǎn)換成真實啟動耗時影響較小杨帽,且系統(tǒng)已經(jīng)對動態(tài)庫的加載做過優(yōu)化,這部分耗時屬于正常嗤军。
  • rebase/binding注盈、Objc setup time:這部分耗時與項目中包含的類、方法數(shù)量形成正比叙赚,從美團(tuán)250M老客,招才貓120M的包大小估算僚饭,這階段耗時屬于正常。
  • initializer time: 此階段會調(diào)用每個Objc和分類的+load方法胧砰,調(diào)用C/C++的構(gòu)造函數(shù)等操作鳍鸵,從分析結(jié)果來看,招才貓在此階段耗時明顯過多尉间,需重點排查偿乖,著重排查+load方法。



T2階段耗時分析

T2階段為 -application:didFinishLaunchingWithOptions: 中SDK初始化乌妒、任務(wù)創(chuàng)建等App部分功能初始化相關(guān)工作汹想,對美團(tuán)的MTAppdelegate類中的didFinishLaunching進(jìn)行逆向分析。

匯編代碼:
圖片5.png

還原OC代碼:
圖片4.png

中間省去N多靜態(tài)分析和動態(tài)調(diào)試撤蚊。。损话。

最終得到美團(tuán)App的啟動任務(wù)管理列表:
圖片3.png

didFinishLaunchingWithOptions 階段

  • 可以看出侦啸,美團(tuán)App在didFinishLaunchingWithOptions中執(zhí)行的主線程Task是相當(dāng)少的,而且很大一部分是屬于基礎(chǔ)類丧枪、基礎(chǔ)數(shù)據(jù)配置的構(gòu)造光涂,這部分耗時是非常少的,必要的幾個任務(wù)也放在了子線程處理拧烦,以最優(yōu)的方式使-didFinishLaunchingWithOptions快速的執(zhí)行完成忘闻,直接去展示頁面,可以說美團(tuán)在這方面是做得很好恋博。
  • 可以發(fā)現(xiàn)這階段中首先有個任務(wù)叫 RunAllLoadFunctions齐佳,可以大膽猜測一下,美團(tuán)是否把本應(yīng)該在main()函數(shù)之前在+load方法中需要做的事情债沮,放在了這個Task中炼吴,以減少+load的數(shù)量。

LaunchForeground 階段
大部分App應(yīng)該都沒有這個階段的一些操作處理疫衩,美團(tuán)也只是在這里進(jìn)行了一些狀態(tài)操作硅蹦,耗時可以忽略的。

viewDidAppear 階段
美團(tuán)將大量(42個)的任務(wù)放在了TabBarController顯示完成之后執(zhí)行闷煤,其中包含了Pay童芹、IM、Spotlight鲤拿、Location假褪、Push、CrashReporter等核心且耗時較大的任務(wù)皆愉。但即使放在了TabBar顯示之后嗜价,也對耗時大的任務(wù)放在了子線程中艇抠,以保證首頁在剛展示后可以流暢的滑動、點擊久锥,不受這些任務(wù)的影響家淤。

notifyT3Completed 階段
根據(jù)這個階段獲取到的堆棧信息,可以猜測分析出應(yīng)該是美團(tuán)App在頁面渲染完成之后做的一些任務(wù)操作瑟由,這些任務(wù)不會影響到App的啟動絮重,所以可以根據(jù)項目需要決定有可借鑒的東西。

圖片10.png

美團(tuán)任務(wù)管理方案:
美團(tuán)除了將任務(wù)劃分做很好之外歹苦,任務(wù)的管理中心也做得很好青伤,美團(tuán)的任務(wù)管理核心可以分為三大部分:
RegisterCenter:對Task進(jìn)行注冊、劃分殴瘦、創(chuàng)建狠角、獲取等等。
TaskRunner:運行啟動階段流程中的任務(wù)蚪腋。
StartTask:任務(wù)者丰歌,存儲任務(wù)的信息,監(jiān)控任務(wù)的執(zhí)行狀態(tài)和耗時等屉凯。

美團(tuán)將每個業(yè)務(wù)線的任務(wù)通過attribute 方式 Chain 到了mach-o中(未驗證立帖,也可能是其他方式),將任務(wù)與模塊悠砚、業(yè)務(wù)線之間直接進(jìn)行了解耦晓勇,在啟動過程中獲取每個階段中任務(wù)的函數(shù)指針進(jìn)行執(zhí)行。

美團(tuán)對每個Task做了很多處理灌旧,可以對每個業(yè)務(wù)線的任務(wù)耗時進(jìn)行監(jiān)控绑咱。對于在didFinishLaunching內(nèi)任務(wù)比較重或需要進(jìn)行任務(wù)解耦的App,美團(tuán)的方案是一個不錯的參考节榜。

簡約模仿的任務(wù)管理流程圖:


圖片1.png

RegisterCenter 核心代碼:
圖片6.png

Task 核心屬性:
圖片9.png
T3階段耗時分析

T3階段涉及東西較多羡玛,簡單對這階段進(jìn)行一個分析。
1宗苍、從上面內(nèi)容知道美團(tuán)的T3階段是到 MTGroupTabbarController的viewDidAppear方法執(zhí)行為止稼稿,對此方法添加斷點可以看見美團(tuán)的啟動首屏。 通過控制臺log輸出及其他信息讳窟,基本上可以確定首屏上半部分的元素內(nèi)容是暫時靜態(tài)的让歼,在未拉取最新內(nèi)容之前有可展示的區(qū)域,不會發(fā)生內(nèi)容白屏的假啟動現(xiàn)象丽啡。

2谋右、再查看TabbarController的代碼,可以發(fā)現(xiàn)有一個Tab根控制器是否創(chuàng)建的屬性补箍,我們對這個屬性在啟動完成后進(jìn)行打印改执,可以看見美團(tuán)App啟動完成后Tab只有一個已經(jīng)創(chuàng)建完成啸蜜, 避免了創(chuàng)建其他Tab所造成的開銷。
image.png

整體耗時對比分析:
以美團(tuán)為標(biāo)準(zhǔn)辈挂,我們對比一下招才貓和美團(tuán)的溫啟動耗時:

image.png

T1階段:上面已經(jīng)對T1階段進(jìn)行了分析衬横,著重排查+load方法造成的影響,從真實的統(tǒng)計時長看终蒂,在T1階段招才貓比美團(tuán)App多耗時了257ms蜂林,從兩個App的體量分析,招才貓App的T1階段耗時在180ms以內(nèi)才屬于正常范圍拇泣。

T2階段:雖然招才貓之前已經(jīng)將非必要的SDK初始化或其他任務(wù)進(jìn)行了管理噪叙,減少或延后到了啟動完成后去執(zhí)行,但以美團(tuán)標(biāo)準(zhǔn)看來霉翔,需要再次對必須在啟動時完成初始化的SDK睁蕾、任務(wù)進(jìn)行梳理,是否仍有延后的可能或在線程中進(jìn)行處理早龟。

T3階段:美團(tuán)和招才貓在此階段耗時相差并不大惫霸,但從觀感上來看,體驗卻相差明顯葱弟。主要原因是美團(tuán)首屏頁可以直接看見一些靜態(tài)展示區(qū)域,而招才貓無論是消息頁面還是附近求職者猜丹,目前都無法在第一時間提供頁面元素芝加, 導(dǎo)致從觀感上認(rèn)為仍然處于啟動階段。

啟動通用優(yōu)化方案

圖片8.png

iOS 啟動優(yōu)化市面上有大量的文章射窒、優(yōu)化方案藏杖, 但大家都會發(fā)現(xiàn)為什么自己App在優(yōu)化后,仍然與美團(tuán)等主流App存在較大的差距脉顿。
分析完美團(tuán)的啟動過程蝌麸,我們基本上能了解到美團(tuán)大部分所做的啟動優(yōu)化工作也是大家所熟知的一些方案,但也能得到一些更為重要的信息:
標(biāo)準(zhǔn):針對于每個App的啟動優(yōu)化艾疟,我們需要優(yōu)化到什么程度来吩,在每個階段的耗時應(yīng)該處于什么樣的一個水平,我們有了一個比較清晰的標(biāo)準(zhǔn)去做對比衡量蔽莱。

監(jiān)控:美團(tuán)對自己的每一個啟動任務(wù)都做了一系列的粒度拆分和監(jiān)控弟疆,在對持續(xù)的版本迭代所造成的增量影響和保持良好的啟動時長能有一個更好的管控機(jī)制。

感悟:如果要做到極致的啟動速度盗冷,就需要對Icon點擊到頁面展示的整個通道怠苔,就如同在一個新的App上去重新鋪好這條路,去過濾不必要或可以優(yōu)化的點仪糖。
技術(shù):美團(tuán)可能將+load方法所做的事情放在了main()函數(shù)之后柑司,是否可提高啟動速度迫肖?(待確認(rèn))

招才貓App啟動分析

以美團(tuán)為標(biāo)準(zhǔn),以招才貓為例攒驰,對App的溫啟動時長進(jìn)行分析蟆湖。

image.png

一、招才貓分析匯總
主要分析方式:工具分析讼育、階段/任務(wù)打點帐姻、通道重鋪、代碼查看奶段、三方庫逆向分析

招才貓啟動過程分析發(fā)現(xiàn)的部分問題:
饥瓷。

痹籍。
省略

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末呢铆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蹲缠,更是在濱河造成了極大的恐慌棺克,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件线定,死亡現(xiàn)場離奇詭異娜谊,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)斤讥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門纱皆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人芭商,你說我怎么就攤上這事派草。” “怎么了铛楣?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵近迁,是天一觀的道長。 經(jīng)常有香客問我簸州,道長鉴竭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任勿侯,我火速辦了婚禮拓瞪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘助琐。我一直安慰自己祭埂,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蛆橡,像睡著了一般舌界。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上泰演,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天呻拌,我揣著相機(jī)與錄音,去河邊找鬼睦焕。 笑死藐握,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的垃喊。 我是一名探鬼主播猾普,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼本谜!你這毒婦竟也來了初家?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤乌助,失蹤者是張志新(化名)和其女友劉穎溜在,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體他托,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡掖肋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了赏参。 大學(xué)時的朋友給我發(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
  • 我被黑心中介騙來泰國打工脱货, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留岛都,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓振峻,卻偏偏與公主長得像臼疫,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子铺韧,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,486評論 2 348

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