App啟動優(yōu)化

極客時間戴銘學習筆記

App啟動干了什么

一般分為冷啟動和熱啟動兩種
冷啟動指, App點擊啟動前, 進程不在系統(tǒng)里, 需要系統(tǒng)新創(chuàng)建一個進程分配給該App, 這是一個完整的啟動過程
熱啟動指, App在冷啟動后用戶將app退到后臺, 在App的進程還在系統(tǒng)里用戶重新進入?的過程

冷啟動階段

三個階段: main函數(shù)執(zhí)行前小槐、main之后台囱、首屏渲染完成后

main()執(zhí)行前

加載可執(zhí)行文件(App的.o文件的集合)
加載動態(tài)鏈接庫, 進行rebase指針調整和bind符號綁定
Objc運行時的初始化處理, 包括Objc相關類的注冊媒区、category注冊砚作、selector唯一性檢查等
初始化, 包括了執(zhí)行+load()方法拱礁、attribute((constructor))修飾的函數(shù)調用揍移、創(chuàng)建C++靜態(tài)全局變量

相應優(yōu)化方法

減少動態(tài)庫加載. 每個庫本身都有依賴關系, 蘋果公司建議使用更少的動態(tài)庫, 并且建議在使用動態(tài)庫的數(shù)量較多時, 盡量將多個動態(tài)庫進行合并. 數(shù)量上, 最多可以支持6個非系統(tǒng)動態(tài)庫合并為一個
減少加載啟動后不會去使用的類或方法
+load()方法里的內容可以放到首屏渲染完成后再執(zhí)行, 或者用+initialize()方法替換掉, 因為, 在一個+load()方法里,進行運行時方法替換操作會帶來4毫秒的消耗
控制C++全局變量的數(shù)量

main()函數(shù)執(zhí)行后

main()函數(shù)執(zhí)行后的階段, 指從main()函數(shù)執(zhí)行開始, 到appDelegate的didFinishLaunchingWithOptions方法里首屏渲染執(zhí)行完成
首頁的業(yè)務代碼都是在這個階段, 也就是首屏渲染前執(zhí)行的, 主要包括了:
首屏初始化所需配置文件的讀寫操作;
首屏列表大數(shù)據(jù)的讀取;
首屏渲染的大量計算等.

相應優(yōu)化方法

從功能上保留首屏渲染必要的初始化功能, 啟動必要的初始化功能,
其他使用時才需要初始化的可以優(yōu)化到之后的時間里執(zhí)行

首屏渲染完成后

非首屏其他業(yè)務服務模塊的初始化滑肉、監(jiān)聽的注冊、配置文件的讀取.
從函數(shù)上看, 這個階段指的是截止到didFinishLaunchingWithOptions方法作用域內執(zhí)行首屏渲染之后的所有方法執(zhí)行完成.
這個優(yōu)化的優(yōu)先級排在最后

功能級別的啟動優(yōu)化

跟前面有點重復, main()函數(shù)開始執(zhí)行后到首屏渲染完成前只處理首屏相關的業(yè)務, 其他非首屏業(yè)務的初始化七咧、監(jiān)聽注冊跃惫、配置文件讀取等放到首屏渲染完成后去做

方法級別的啟動優(yōu)化

某些方法大量調用會增加耗時.

監(jiān)控啟動速度兩種方案

  1. 定時抓取主線程上的方法調用堆棧, 計算一段時間里各個方法的耗時,比如Time Profiler
  2. 對objc_msgSend方法進行hook來掌握所有方法的執(zhí)行耗時, 通過監(jiān)聽所有的Objective-C里方法執(zhí)行來實現(xiàn)
    objc_msgSend方法執(zhí)行的邏輯是: 先獲取對象對應類的信息, 再獲取方法的緩存, 根據(jù)方法的selector查找函數(shù)指針, 經(jīng)過異常錯誤處理后, 最后跳到對應函數(shù)的實現(xiàn)
    使用fishhook的方法來實現(xiàn)

基于靜態(tài)庫插樁的二進制重排啟動優(yōu)化 (手淘的最新實踐)

  1. App 啟動時PageFault的性能分析
  2. 靜態(tài)庫插樁重排方案的技術原理

App啟動和PageFault

當我們向操作系統(tǒng)申請內存時, 操作系統(tǒng)并不是直接分配給我們物理內存, 而是只標記當前進程擁有該段內存, 當真正使用這段內存時才會分配. 這種延遲分配物理內存的方式就通過page fault機制來實現(xiàn)的. 當我們訪問一個內存地址時, 如果該地址非法, 或者我們對其沒有訪問權限, 或者該地址對應的物理內存還未分配, cpu都會生成一個page fault, 進而執(zhí)行操作系統(tǒng)的page fault handler. 如果是因為還未分配物理內存, 操作系統(tǒng)會立即分配物理內存給當前進程, 然后重試產(chǎn)生這個page fault的內存訪問指令
來自淘系技術官方

App在啟動時, 需要執(zhí)行各種函數(shù), 我們需要讀取TEXT段代碼到物理內存中, 這個過程會發(fā)生缺頁中斷, 由于啟動時所需要執(zhí)行的代碼分布在TEXT段的各個部分, 會讀取很多頁面, 導致啟動時Page Fault數(shù)量非常多. 與直接訪問物理內存不同, page fault過程大部分由軟件完成, 消耗時間比較久, 所以是影響啟動性能的一個關鍵指標.
手淘啟動時首先調用的幾個方法會分布在虛擬內存的各個頁面中, 執(zhí)行這些方法時, 需要從讀取到物理內存中, 就會產(chǎn)生多次page fault.
如果能將啟動階段需要的讀取代碼集中排布, 將這些方法全都放到相鄰的區(qū)域中, 我們讀取這些方法可能就只需要極少的page fault次數(shù). 可以減少不必要的page fault時間.達到優(yōu)化啟動時間的效果.
重排前后的函數(shù)在頁面的布局對比


來自淘系技術官方

重排方案

如何獲取方法的執(zhí)行順序

為了生存order_file, 我們需要確定應用啟動時方法的執(zhí)行順序.
抖音通過靜態(tài)掃描和運行時Trace等方法確定order_file, 該方案無法覆蓋initialize、block和C++通過寄存器的間接函數(shù)調用
Facebook分享過通過llvm插樁的確定order_file的方案, 需要使用源碼重新打包.

靜態(tài)庫插樁

我們編譯過的靜態(tài)庫由.o文件組成, 我們可以對.o中的函數(shù)代碼進行修改, 在每個函數(shù)的開頭插入調用我們指定記錄函數(shù)的指令

生成order file

linkmap記錄了連接過程中的相關信息. 其中包含鏈接用到的symbol相關信息.通過pc address減去slide得到的地址, 我們可以在linkmap中找到對應的symbol

address = pc - slide. // 因為ASLR艾栋, APP 可執(zhí)行文件隨機載入的原因爆存,需要處理一下偏移
量。
我們需要將之前記錄的地址轉換成對應的符號, 為了真實還原線上的執(zhí)行環(huán)境, 在app中簡單的記錄了pc地址和image的偏移量. 通過解析linkmap, 獲取函數(shù)的地址區(qū)間, 得到距離address最近的symbol, 生成order_file

更改符號的排列順序

默認情況下, Id鏈接器會按照鏈接的順序將各個.o文件的數(shù)據(jù)重新布局生成可執(zhí)行文件.Id鏈接器提供-order-file選項操控數(shù)據(jù)排列的順序.在Xcode中可以通過Order File選項指定符號排序文件.

重排之后效果很不錯

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末蝗砾,一起剝皮案震驚了整個濱河市先较,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌悼粮,老刑警劉巖闲勺,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異扣猫,居然都是意外死亡菜循,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門申尤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來癌幕,“玉大人衙耕,你說我怎么就攤上這事∩自叮” “怎么了臭杰?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長谚中。 經(jīng)常有香客問我渴杆,道長,這世上最難降的妖魔是什么宪塔? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任磁奖,我火速辦了婚禮,結果婚禮上某筐,老公的妹妹穿的比我還像新娘比搭。我一直安慰自己,他們只是感情好南誊,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布身诺。 她就那樣靜靜地躺著,像睡著了一般抄囚。 火紅的嫁衣襯著肌膚如雪霉赡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天幔托,我揣著相機與錄音穴亏,去河邊找鬼。 笑死重挑,一個胖子當著我的面吹牛嗓化,可吹牛的內容都是我干的。 我是一名探鬼主播谬哀,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼刺覆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了史煎?” 一聲冷哼從身側響起谦屑,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎劲室,沒想到半個月后伦仍,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體结窘,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡很洋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了隧枫。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片喉磁。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡谓苟,死狀恐怖,靈堂內的尸體忽然破棺而出协怒,到底是詐尸還是另有隱情涝焙,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布孕暇,位于F島的核電站仑撞,受9級特大地震影響,放射性物質發(fā)生泄漏妖滔。R本人自食惡果不足惜隧哮,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望座舍。 院中可真熱鬧沮翔,春花似錦、人聲如沸曲秉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽承二。三九已至榆鼠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間亥鸠,已是汗流浹背璧眠。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留读虏,地道東北人责静。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像盖桥,于是被迫代替她去往敵國和親灾螃。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內容