APP啓動那點事

一般而言,App的啓動時間指的是從用戶點擊App開始,到用戶看到第一個界面之間的時間。總結來書,App的啓動包括三個階段:

  1. main()函數執行前;
  2. main()函數執行後;
  3. 首屏渲染完成後。

main()函數執行前

在 main() 函數執行前,系統主要會做下面幾件事:

  • 加載可執行文件 (App 的 .o文件集合)
  • 加載動態鏈接庫,進行rebase 指針調整和bind符號綁定
  • ObjC運行時的初始處理,包括ObjC相關類的註冊、category註冊、selector唯一性檢查等
  • 初始化,包括可執行 +load()方法、attribute((constructor))修飾的函數的調用、創建C++靜態全局變量

對於這個階段啓動速度優化來說,可以做的事情如下

  • 減少動態庫加載
  • 減少加載啓動後不會去使用的類或者方法
  • +load() 方法裏的內容可以放到首屏渲染完成後再執行,或者使用+initialize()方法替換掉
  • 控制 C++全局變量的數量

main() 函數執行之後

main() 函數執行後的階段,指的是從main() 函數執行開始,到 appDelegate 的 didFinishLaunchingWithOptions 方法裏首屏渲染相關方法執行完成。

首頁業務代碼都是要在這個階段,也就是首屏渲染前執行的,只要包括:

  • 首屏初始化所需配置文件的讀寫操作
  • 首屏列表數據的讀取
  • 首屏渲染的大量計算等

很多時候我們會把各種初始化工作放到這個階段執行,導致渲染完成滯後。我們應該從功能上梳理出哪些是首屏渲染必要的初始化功能,哪些是App啓動必要的初始化功能,而哪些是只需要在對應功能開始使用時才需要初始化的。梳理完成後,將這些初始化功能分別放到適合的階段進行。

首屏渲染完成後

首屏渲染後的這個階段,主要完成的是,非首屏其他業務服務模塊的初始化、監聽的註冊、配置文件的讀取等等。從函數上來看,這個階段值得就是截止到 didFinishLaunchingWithOptions 方法作用域內執行首屏渲染之後的所用方法執行完成。簡單來說這個階段就是從渲染完成時開始,到 didFinishLaunchingWithOptions 方法作用域結束時結束。

對於App啓動速度的優化我們可以從 功能級別和方法級別 去優化

功能級別的啓動優化

優化思路是:main() 函數開始執行後到首屏渲染完成前只處理首屏相關的業務,其他非首屏業務的初始化、監聽註冊、配置文件讀取等都放到首屏渲染完成後。

方法級別的啓動優化

檢查首屏渲染完成前主線程上有哪些耗時方法,將沒有必要的耗時方法滯後或者異步執行。通常情況下,耗時較長的方法主要發生在計算大量數據的情況下,具體的體現是 加載、編輯、存儲圖片和文件等資源。

 

對App啓動速度的監控,只要有兩種手段

第一種方法是,定時抓取主線程上的方法調用堆棧,計算一段時間裏各個方法的耗時。 Xcode 工具套件裏自帶的 Time Profile 就是採用這種方式。

第二種方法是,對 objc_msgSend 方法進行 hook 來掌握所有方法的執行耗時。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章