iOS 啟動優化 二進位制重排
阿新 • • 發佈:2020-06-24
iOS 啟動優化 二進位制重排
配置
-
在Build Settings中新增編譯選項Other C Flags增加
-fsanitize-coverage=func,trace-pc-guard 如果是OC Swift混編, 則在Other Swift Flags增加-sanitize-coverage=func
,`-sanitize=undefined -
統計程式啟動的函式執行情況在首頁的viewDidAppear函式中加上生成orderFile的函式,然後執行app,會在app的沙盒的tmp目錄下生成,htclangtrace.order的檔案,獲取tmp 下的htclangtrace.order 匯入工程
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[HTClangTrace generateOrderFile];
}
複製程式碼
- 在Build Settings中搜索Order File 設定為htclangtrace.order的路徑 具體獲取 HTClangTrace.h 檔案如下
//
// HTClangTrace.m
// HTScore_iOS
//
// Created by muxinjian on 2020/6/3.
// Copyright © 2020 huatu. All rights reserved.
//
#import "HTClangTrace.h"
#import <dlfcn.h>
#import <libkern/OSAtomic.h>
@implementation HTClangTrace
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.
for (uint32_t *x = start; x < stop; x++)
*x = ++N; // Guards should start from 1.
}
//原子佇列
static OSQueueHead symbolList = OS_ATOMIC_QUEUE_INIT;
//定義符號結構體
typedef struct {
void *pc;
void *next;
} SymbolNode;
void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
if (!*guard) return;
void *PC = __builtin_return_address(0);
SymbolNode *node = malloc(sizeof(SymbolNode));
*node = (SymbolNode){PC,NULL};
OSAtomicEnqueue(&symbolList,node,offsetof(SymbolNode,next));
}
+ (void)generateOrderFile {
NSMutableArray <NSString *> *symbolNames = [NSMutableArray array];
while (YES) {
SymbolNode * node = OSAtomicDequeue(&symbolList,next));
if (node == NULL) {
break;
}
Dl_info info;
dladdr(node->pc,&info);
NSString *name = @(info.dli_sname);
// 判斷是不是oc方法,是的話直接加入符號陣列
BOOL isInstanceMethod = [name hasPrefix:@"-["];
BOOL isClassMethod = [name hasPrefix:@"+["];
BOOL isObjc = isInstanceMethod || isClassMethod;
NSString * symbolName = isObjc ? name: [@"_" stringByAppendingString:name];
[symbolNames addObject:symbolName];
}
// 取反:將先呼叫的函式放到前面
NSEnumerator * emt = [symbolNames reverseObjectEnumerator];
// 去重:由於一個函式可能執行多次,__sanitizer_cov_trace_pc_guard會執行多次,就加了重複的了,所以去重一下
NSMutableArray<NSString *> *funcs = [NSMutableArray arrayWithCapacity:symbolNames.count];
NSString *name;
while (name = [emt nextObject]) {
if (![funcs containsObject:name]) {
[funcs addObject:name];
}
}
// 由於trace了所有執行的函式,這裡我們就把本函式移除掉
[funcs removeObject:[NSString stringWithFormat:@"%s",__FUNCTION__]];
// 寫order檔案
NSString *funcStr = [funcs componentsJoinedByString:@"\n"];
NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"htclangtrace.order"];
NSData *fileContents = [funcStr dataUsingEncoding:NSUTF8StringEncoding];
[[NSFileManager defaultManager] createFileAtPath:filePath contents:fileContents attributes:nil];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]){
NSLog(@"orderPath:%@",filePath);
}else{
NSLog(@"生成orderPath失敗");
}
}
#pragma mark - Util
+ (BOOL)isObjcMethodBySymbolName:(NSString *)symbolName {
BOOL isInstanceMethod = [symbolName hasPrefix:@"-["];
BOOL isClassMethod = [symbolName hasPrefix:@"+["];
return isInstanceMethod || isClassMethod;
}
@end
複製程式碼