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
之后编译代码