這是啓動速度提高的第三篇:ios
第一篇講了動態庫轉靜態庫和二進制重排帶來的啓動優化以及其原理。git
第二篇講了動態庫轉靜態庫到底帶來了哪些改變,以及實踐中遇到的問題應該如何解決。github
本篇將介紹懶人版的Clang插樁導出啓動相關的符號表,原理能夠參考《我是如何讓微博綠洲的啓動速度提高30%的》。swift
第一篇文章介紹了Clang插樁能夠導出主工程啓動相關的符號表,有朋友問到了若是涉及到CocoaPods導入的三方庫,該如何進行插樁呢?ruby
最近我把這一塊整理了一下,作了一個CocoaPods的庫 YCSymbolTracker ,下載庫能夠獲得同款Demo。(以爲不錯的話,能夠點一個Star★,biu~)app
咱們一步一步來,首先看一下這個庫如何導出主工程啓動相關的符號表。函數
platform :ios, '8.0'
use_frameworks!
target 'Demo' do
pod 'YCSymbolTracker', '~> 0.1.0'
end
複製代碼
在AppDelegate
中配置導出地址:post
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.rootViewController = [[YCViewController alloc] init];
[self.window makeKeyAndVisible];
[SwiftDemo swiftTestLoad];
NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"demo.order"];
NSLog(@"%@", filePath);
[YCSymbolTracker exportSymbolsWithFilePath:filePath];
return YES;
}
複製代碼
拿到控制檯輸出的地址,打開文件:flex
咱們看到了主工程啓動相關的符號表。優化
咱們添加一個三方庫SDWebImage
,你也能夠嘗試其餘庫。
platform :ios, '8.0'
use_frameworks!
target 'Demo' do
pod 'SDWebImage'
pod 'YCSymbolTracker', '~> 0.1.0'
end
複製代碼
在AppDelegate
中添加SDWebImage相關的代碼:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.rootViewController = [[YCViewController alloc] init];
[self.window makeKeyAndVisible];
[SwiftDemo swiftTestLoad];
[SDWebImageManager.sharedManager cancelAll]; // 添加的代碼
NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"demo.order"];
NSLog(@"%@", filePath);
[YCSymbolTracker exportSymbolsWithFilePath:filePath];
return YES;
}
複製代碼
咱們再導出一次:
咱們發現咱們的order文件沒有發生變化。這是由於咱們的Clang插樁只覆蓋了主工程,沒有包括三方庫!
在Pod工程 SDWebImage 中 Build Settings 的 Other C Flags添 -fsanitize-coverage=func,trace-pc-guard 配置。
若是是Swift的三方庫 Other Swift Flags 添加 -sanitize=undefined -sanitize-coverage=func 配置。
這時若是咱們直接執行構建的話會報錯。
Undefined symbol: ___sanitizer_cov_trace_pc_guard_init
Undefined symbol: ___sanitizer_cov_trace_pc_guard
複製代碼
若是看了第一篇文章,或者熟悉這個問題的同窗應該立刻就明白了,找不到這個符號。咱們的 YCSymbolTracker 庫中實際上是有這個符號的,可是因爲它們都是動態庫(獨立), SDWebImage 不能直接訪問到 YCSymbolTracker 中的函數。可是咱們不能修改三方庫的代碼,或者修改三方庫的podspec文件來修改依賴關係。那麼如何讓 SDWebImage 依賴 YCSymbolTracker 從而訪問到這兩個函數呢?
選擇Pods工程的 SDWebImage ,在Frameworks and Libraries中添加 YCSymbolTracker 。
修改 YCSymbolTracker 是否Embed:
這樣咱們就爲 SDWebImage 添加了 YCSymbolTracker 做爲依賴,能夠在 Build Phase 的 Dependencies 中驗證:
配置好以後咱們再跑一次:
嗒噠~如今咱們能夠看到[SDWebImageManager.sharedManager cancelAll];
執行後相關的符號了!也就是說咱們拿到了主工程和三方庫啓動相關的符號表了。
主工程和三方庫的插樁導出符號表的原理咱們已經明白了,可是一個工程可能導入了不少三方庫,我不可能一個一個去弄吧。不用擔憂,我提供了懶人腳原本完成這個事情。
在Podfile最後添加:
post_install do |installer|
require './Pods/YCSymbolTracker/YCSymbolTracker/symbol_tracker.rb'
symbol_tracker(installer)
end
複製代碼
注意: Demo和正式版路徑不太同樣,這裏以正式版的路徑爲例。
若是Podfile中採用use_frameworks!,則(幾乎)全部庫是動態庫。
執行完pod install
以後就會執行上面的ruby腳本,腳本中會完成三方庫的Clang插樁配置和依賴配置。
若是Podfile中不採用use_frameworks!,則(幾乎)全部庫是靜態庫。
靜態庫咱們都知道,會被合併到主工程的Mach-O文件中,因此能夠直接在Pod工程 SDWebImage 中 Build Settings 的 Other C Flags添 -fsanitize-coverage=func,trace-pc-guard 配置,而不會報找不到符號的錯。
執行完pod install
以後就會執行上面的ruby腳本,因此腳本中沒有添加依賴配置,只添加Clang插樁配置。
還有什麼問題歡迎你們提出來~ Have FUN~
若是以爲本文對你有所幫助,給我點個贊吧~