1. 程式人生 > IOS開發 >ezbuy iOS APP啟動時間優化

ezbuy iOS APP啟動時間優化

來源: APP研發(上海) 團隊 - 許贇

摘要

(App總啟動時間)T = (main()之前的載入時間)T1 + (main()之後的載入時間)T2

T1 = 系統dylib(動態連結庫)和自身App可執行檔案的載入;

T2 = main方法執行之後到AppDelegate類中的- (BOOL)Application:(UIApplication *)Application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法執行結束前這段時間,主要是構建第一個介面,並完成渲染展示。

注: 以下測試時間如無特殊說明,均在 macOS Mojave10.14.3

,Xcode10.2.1,iPhone6 plus,iOS12.3.1,ezbuy-UAT的環境下!!!

一. T1(main函式之前的載入時間)

T1可以通過在EditScheme中新增 DYLD_PRINT_STATISTICS 這個環境變數來檢視.

圖片描述
注意為了接近真實狀態,最好是把Bulid Configration 改成Release,並且連線真機而不是模擬器來檢視.

ezbuy-UAT pre-main時間圖:

圖片描述

pre-main階段如何優化

在preMain階段因為涉及到底層,目前能做的工作不多.最多是刪除一些Pod中不再用到的庫. 如果後續有人對這部分的優化比較感興趣可以移步

這裡

二. (main()之後的載入時間)T2

這段時間的衡量在專案中列印即可,因為swift把main函式和appDelegate合併成了一個檔案,所以專案中找不到main函式的入口,但我們可以自己建立一個:

1 建立一個名為main.swift的檔案,在檔案中寫入以下程式碼(swift5):

import Foundation
import UIKit

var START_TIME:CFAbsoluteTime = CFAbsoluteTimeGetCurrent()
UIApplicationMain(CommandLine.argc,CommandLine.unsafeArgv,nil,NSStringFromClass(AppDelegate.self))
複製程式碼

2 到APPDelegate檔案中,註釋掉 @UIApplicationMain

3 在 didFinishLaunchingWithOptions 方法 return true 前面加上以下程式碼

func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    
	/*...*/

   	NSLog("*** App Launched in: %f sec",CFAbsoluteTimeGetCurrent() - START_TIME)
    
    return true
  }
複製程式碼

目前執行專案得到的結果是

圖片描述

main()階段如何優化

這一階段的優化主要是減少 didFinishLaunchingWithOptions 方法裡的工作,在 didFinishLaunchingWithOptions方法裡,我們會建立應用的window,指定其rootViewController,呼叫windowmakeKeyAndVisible方法讓其可見。由於業務需要,我們會初始化各個二方/三方庫,設定系統UI風格,檢查是否需要顯示引導頁、是否需要登入、是否有新版本等,由於歷史原因,這裡的程式碼容易變得比較龐大,啟動耗時難以控制。 所以,滿足業務需要的前提下,didFinishLaunchingWithOptions在主執行緒裡做的事情越少越好。在這一步,我們可以做的優化有:

  1. 梳理各個二方/三方庫,找到可以延遲載入的庫,做延遲載入處理,比如放到首頁控制器的viewDidAppear方法裡。
  2. 梳理業務邏輯,把可以延遲執行的邏輯,做延遲執行處理。比如檢查新版本、註冊推送通知等邏輯。
  3. 避免複雜/多餘的計算。
  4. 避免在首頁控制器的viewDidLoadviewWillAppear做太多事情,這2個方法執行完,首頁控制器才能顯示,部分可以延遲建立的檢視應做延遲建立/懶載入處理。
  5. 採用效能更好的API。
  6. 首頁控制器用純程式碼方式來構建。

三. ezbuyApp啟動時間優化做的工作

1) pre-main()階段

podfile中刪掉MenuItemKit,因為MenuItemKit時間本身載入就只有30ms左右(見上面pre-main時間圖),已經預料到時間應該並無顯著差異 優化前pre-main十次平均時間 1.29s,優化後 1.33s

2) main()方法之後

1 把didFinishLaunchingWithOptions中能放到非同步執行緒執行的程式碼都放到非同步執行緒中. 2 把app啟動動畫時間從0.5s縮短到0.2s

  1. main函式執行時到didFinishLaunchingWithOptions結束,執行10次的平均時間: 優化前 3.56,優化後 1.08
  2. main函式執行時到ShopHomeDefaultViewController viewDidAppear 方法結束時,執行10次的平均時間: 優化前 4.85,優化後2.07

補充: 下午因為刪掉MenuItemKit重新運行了十次,優化後的平均資料分別為 2.36`,可能是手機本身由於下午資源佔用比較多,所以時間較上午長

參考文章: iOS App Launch time analysis and optimizations Slow App Startup Times 今日頭條iOS客戶端啟動速度優化 阿里資料iOS端啟動速度優化的一些經驗 Get your app launch time with Swift How to subclass UIApplication using UIApplicationMain