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%。