在性能優(yōu)化過程中,啟動速度優(yōu)化一直是一個比較大的點林束。Apple 官方期望 APP 的啟動時間為 0.4 s像棘,用戶的期待時間為 2 s (來自調查)。不過作為開發(fā)者壶冒,當然希望我們的 APP 的啟動速度能夠盡可能的快缕题。若是對 Time Profiler 不熟悉的同學可以先閱讀一下先前的文章 Instruments 之 Time Profiler 使用。
冷啟動和熱啟動
APP 啟動分為冷啟動(Cold Launches),當 APP 長時間沒有被啟動的時候胖腾,用戶再次啟動 APP 的時候就是冷啟動烟零,若是手機重啟之后,APP 的第一次啟動也是冷啟動咸作;冷啟動對應的是熱啟動(Warm Launches),當 APP 啟動時需要的 dylibs 仍然停留在設備的磁盤緩存的時候瓶摆,這個時候就是熱啟動,熱啟動的速度會更快性宏。
優(yōu)化案例
使用 Xcode 版本為 8.3.2 群井,設備為 iPhone 6 ,系統(tǒng)版本 10.3.1毫胜。 APP 每次啟動之前需要重啟一下手機书斜,達到冷啟動的效果诬辈。案例使用 raywenderlich 的
Catstagram 啟動優(yōu)化。該案例是一個帶圖片的列表荐吉。
優(yōu)化 before main()
APP 啟動優(yōu)化可以分為 2 個部分焙糟,一個部分在 main() 函數(shù)之前,另一部分在 main()函數(shù)之后样屠。對于 APP 的啟動細節(jié)可以參考 WWDC 的 Optimizing App Startup Time 章節(jié)穿撮,本文主要講使用 Time Profiler 來分析 APP ,然后根據分析結果來優(yōu)化 APP痪欲,著重講解 Time Profiler 的使用過程悦穿。
接下來,打開 Catstagram 案例业踢,添加 Scheme 的 DYLD_PRINT_STATISTICS 參數(shù)栗柒,并設置值為 YES,見下圖所示知举。該DYLD_PRINT_STATISTICS參數(shù)用于讓 Xcode 控制臺輸出 APP 在 before main() 時機之前的花費時間瞬沦。
設置好了之后,Command + R 在冷啟動情況下啟動 APP 雇锡,可以看到控制臺的輸出
Total pre-main time: 1.5 seconds (100.0%)
dylib loading time: 814.09 milliseconds (52.6%)
rebase/binding time: 52.20 milliseconds (3.3%)
ObjC setup time: 241.27 milliseconds (15.6%)
initializer time: 437.29 milliseconds (28.3%)
slowest intializers :
libSystem.B.dylib : 19.26 milliseconds (1.2%)
AsyncDisplayKit : 145.63 milliseconds (9.4%)
Catstagram : 277.81 milliseconds (17.9%)
重點關注 Total pre-main time: 1.5 seconds (100.0%) 的信息逛钻,冷啟動情況在 pre-main 時機中可以看到信息 dylib loading time: 814.09 milliseconds (52.6%) ,也就是說我們的 dylib loading time 加載時間占據了 52.6% 锰提。聯(lián)想到我們的第三方庫是采用 pod 管理绣的,并且是 use_frameworks ,frameworks 是一個可優(yōu)化點欲账,
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target 'Catstagram' do
use_frameworks!
pod 'AFNetworking'
pod 'AsyncDisplayKit', '~> 2.2'
pod 'Yoga', '~> 1.3'
pod 'Firebase', '~> 3.15'
#pod 'FirebaseUI', '~> 3.1'
end
這個 frameworks 是一個可優(yōu)化點屡江,打開 Podfile,并注釋掉 use_frameworks ,然后命令行執(zhí)行 pod install 命令 赛不,更新工程惩嘉,可以看到工程設置發(fā)生了變化。
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target 'Catstagram' do
#use_frameworks!
pod 'AFNetworking'
pod 'AsyncDisplayKit', '~> 2.2'
pod 'Yoga', '~> 1.3'
pod 'Firebase', '~> 3.15'
#pod 'FirebaseUI', '~> 3.1'
end
修改好了之后踢故,Command + R 在冷啟動情況下啟動 APP 文黎,查看控制臺的輸出。
Total pre-main time: 1.1 seconds (100.0%)
dylib loading time: 470.55 milliseconds (39.6%)
rebase/binding time: 31.07 milliseconds (2.6%)
ObjC setup time: 255.35 milliseconds (21.4%)
initializer time: 430.58 milliseconds (36.2%)
slowest intializers :
libSystem.B.dylib : 12.89 milliseconds (1.0%)
Catstagram : 792.04 milliseconds (66.6%)
從 log 中可以看到明顯的變化殿较,Total pre-main time 由之前 1.5 seconds 降到 1.1 seconds 耸峭。dylib loading time 由之前的 814.09 milliseconds (52.6%) 降到 470.55 milliseconds (39.6%) 。優(yōu)化效果非常明顯淋纲。
優(yōu)化 after main()
優(yōu)化完 before main() 之后劳闹,開始來優(yōu)化 after main()。從圖中可以看出啟動優(yōu)化的點是集中在 UIApplicationMain()上。
打開 Instruments 選擇 Time Profiler 來分析 APP本涕。
選擇 APP 生命周期中的 Launching 生命周期來分析业汰,如上圖所示,可以清晰的看到耗時操作主要發(fā)生在 log 操作中菩颖,所以我們回到關于 log 的這段代碼代碼中样漆,它可能是一個可以優(yōu)化的點。
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
let appearance = UINavigationBar.appearance()
appearance.backgroundColor = .white
appearance.barTintColor = .white
CoolLogger.reportLogs()
return true
}
上述打 log 代碼在 main 線程中執(zhí)行晦闰,所以這段代碼是可以優(yōu)化的放祟,我們將這段代碼放到非 main 線程中執(zhí)行。
DispatchQueue.global(qos: .background).async {
CoolLogger.reportLogs()
}
修改代碼之后呻右,重新啟動手機跪妥,讓 APP 進行冷啟動,繼續(xù)使用 Time Profiler 分析 APP,從下圖的分析結果總可以看到優(yōu)化取得了效果窿冯,APP 的 Laucning 生命周期沒有出現(xiàn) APP 的生命周期中,說明使用了及其短的時間來完成啟動确徙,這時間長度可以忽略醒串。
總結
Time Profiler 可以看到代碼的運行時長,配合它的Lift Cycle 工具可以用來優(yōu)化 APP 的啟動速度鄙皇。 Time Profiler 只是一個工具芜赌,它只能幫助記錄 APP 的運行狀態(tài),而開發(fā)者可以根據記錄的狀態(tài)分析 APP 的耗時操作伴逸,然后進行修改缠沈,再用 Time Profiler 驗證。
參考
本文是 raywenderlich 的課程筆記错蝴,內容參考 Practical Instruments 課程
1洲愤、Demo 項目 https://files.betamax.raywenderlich.com/attachments/videos/786/0965b118-95eb-492f-804c-3135c7347130.zip
2、https://videos.raywenderlich.com/courses/74-practical-instruments/lessons/4