共计 2770 个字符,预计需要花费 7 分钟才能阅读完成。
1. 优化前 缺页中断耗时 (第一次装置)
如果有, 请先删除 -fsanitize-coverage=func,trace-pc-guard
配置.
删除 app, 革除 Xcode 缓存 ;
Xcode 菜单栏 > Product > Profile (快捷键 command+I) , 期待 running 实现;
呈现 Instruments
界面, 抉择System Trace
;
启动我的项目, 到第一个界面呈现后进行, 期待剖析,
搜寻Main Thread
, 抉择 Virtu Memory
, 查看缺页中断File Backed Page in
次数与工夫;
2. 获取启动时加载的所有函数符号
删除 app, 在 Xcode Build Settings
> Apple Clang - Custom Compiler Flags
> Other C Flags
中
增加 -fsanitize-coverage=func,trace-pc-guard
,
在启动后会呈现的 第一个界面 中增加如下代码:
#import <dlfcn.h>
#import <libkern/OSAtomic.h>
// 原子队列
static OSQueueHead symboList = OS_ATOMIC_QUEUE_INIT;
// 定义符号构造体
typedef struct {
void * pc;
void * next;
} SymbolNode;
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("[clang] INIT: %p %p\n", start, stop);
for (uint32_t *x = start; x < stop; x++)
*x = ++N; // Guards should start from 1.
}
void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {//if (!*guard) return; // Duplicate the guard check.
void *PC = __builtin_return_address(0);
SymbolNode * node = malloc(sizeof(SymbolNode));
*node = (SymbolNode){PC,NULL};
// 入队
// offsetof 用在这里是为了入队增加下一个节点找到 前一个节点 next 指针的地位
OSAtomicEnqueue(&symboList, node, offsetof(SymbolNode, next));
}
void tmpOrderFile() {NSMutableArray<NSString *> * symbolNames = [NSMutableArray array];
while (true) {
//offsetof 就是针对某个构造体找到某个属性绝对这个构造体的偏移量
SymbolNode * node = OSAtomicDequeue(&symboList, offsetof(SymbolNode, next));
if (node == NULL) break;
Dl_info info;
dladdr(node->pc, &info);
NSString * name = @(info.dli_sname);
// 增加 _
BOOL isObjc = [name hasPrefix:@"+["] || [name hasPrefix:@"-["];
NSString * symbolName = isObjc ? name : [@"_" stringByAppendingString:name];
// 去重
if (![symbolNames containsObject:symbolName]) {[symbolNames addObject:symbolName];
}
}
// 干掉本人
NSString * thisFunc = [NSString stringWithFormat:@"_%s",__FUNCTION__];
if ([symbolNames containsObject:thisFunc]) {[symbolNames removeObject:thisFunc];
}
// 取反
NSMutableArray * symbolAry = [NSMutableArray arrayWithArray:[[symbolNames reverseObjectEnumerator] allObjects]];
NSLog(@"[clang] %@",symbolAry);
// 将后果写入到文件
NSString * funcString = [symbolAry componentsJoinedByString:@"\n"];
NSString * filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"lb.order"];
NSData * fileContents = [funcString dataUsingEncoding:NSUTF8StringEncoding];
BOOL result = [[NSFileManager defaultManager] createFileAtPath:filePath contents:fileContents attributes:nil];
if (result) {NSLog(@"[clang] %@",filePath);
}else{NSLog(@"[clang] 文件写入出错");
}
}
而后在 viewDidAppear
中调用tmpOrderFile()
, (或者在其余事件办法里调用也能够).
在第一个界面呈现后 (或者其余事件办法触发并实现后), 下载文件.
下载的文件右击 ” 显示包内容 ”, 找到 tmp 文件下的 lb.order 文件, 外面就是启动加载的所有我的项目符号了.
3. 重排启动符号
将 ld.order 文件拷贝到我的项目目录下;
在 Build Setting 中搜寻 order file
, 写入 ld.order 文件门路:
从新执行步骤 1, 可查看优化后的成果.
查看符号重排程序
Build Setting 中搜寻 link map, 批改 Write Link Map File
为 YES, 运行后到 Products
同级目录 Intermediates.noindex
下 找到 ..._ios.build
目录下一个 txt 文件, 搜寻 # Symbols:
, 就是我的项目编译的符号程序, 能够与 ld.order 程序比照一下, 雷同则阐明有成果.
4. 优化后 缺页中断耗时
这个我的项目布局良好, 所以优化空间没有很大.
缺页中断速度晋升了 32.44%;总体速度放慢 46.34ms,晋升 29.32%。