iOS App啓動優化(四):編譯期插樁 && 獲取方法符號函數
iOS App啓動優化(五):收集符號 && 生成 Order Filepost
優化前 ui
優化後spa
Target -> Build Setting -> Custom Complier Flags ->
code
Other C Flags
添加component
-fsanitize-coverage=func,trace-pc-guard
Other Swift Flags
添加
-sanitize-coverage=func
-sanitize=undefined
添加到啓動最先的那個 ViewController
便可。
#import "dlfcn.h"
#import <libkern/OSAtomic.h>
複製代碼
void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
static uint64_t N; // Counter for the guards.
if (start == stop || *start) return; // Initialize only once.
printf("INIT: %p %p\n", start, stop);
for (uint32_t *x = start; x < stop; x++)
*x = ++N; // Guards should start from 1.
}
//初始化原子隊列
static OSQueueHead list = OS_ATOMIC_QUEUE_INIT;
//定義節點結構體
typedef struct {
void *pc; //存下獲取到的PC
void *next; //指向下一個節點
} Node;
void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
void *PC = __builtin_return_address(0);
Node *node = malloc(sizeof(Node));
*node = (Node){PC, NULL};
// offsetof() 計算出列尾,OSAtomicEnqueue() 把 node 加入 list 尾巴
OSAtomicEnqueue(&list, node, offsetof(Node, next));
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSMutableArray *arr = [NSMutableArray array];
while(1){
//有進就有出,這個方法和 OSAtomicEnqueue() 類比使用
Node *node = OSAtomicDequeue(&list, offsetof(Node, next));
//退出機制
if (node == NULL) {
break;
}
//獲取函數信息
Dl_info info;
dladdr(node->pc, &info);
NSString *sname = [NSString stringWithCString:info.dli_sname encoding:NSUTF8StringEncoding];
printf("%s \n", info.dli_sname);
//處理c函數及block前綴
BOOL isObjc = [sname hasPrefix:@"+["] || [sname hasPrefix:@"-["];
//c函數及block須要在開頭添加下劃線
sname = isObjc ? sname: [@"_" stringByAppendingString:sname];
//去重
if (![arr containsObject:sname]) {
//由於入棧的時候是從上至下,取出的時候方向是從下至上,那麼就須要倒序,直接插在數組頭部便可
[arr insertObject:sname atIndex:0];
}
}
//去掉 touchesBegan 方法 啓動的時候不會掉用到這個
[arr removeObject:[NSString stringWithFormat:@"%s",__FUNCTION__]];
//將數組合成字符串
NSString * funcStr = [arr componentsJoinedByString:@"\n"];
//寫入文件
NSString * filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"link.order"];
NSData * fileContents = [funcStr dataUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@", filePath);
[[NSFileManager defaultManager] createFileAtPath:filePath contents:fileContents attributes:nil];
}
複製代碼
NSLog(@"%@", filePath);
斷點viewDidLoad
裏面調用touchesBegan:withEvent:
也能夠link.order
的路徑Finder
前往路徑取出 order file
link.order
的路徑放到工程根目錄Target -> Build Setting -> Linking -> Order File
設置路徑order file
的設置還原clean
之後編譯代碼