摘录:ios启动优化:二进制重排
先查看需要优化项目的排列以及大体的Page Fault
1、Xcode:【Build Settings 】-> 【Write Link Map File】 -> YES;
2、然后Clean项目,运行,选择Products 中的项目-> Show in Finder;
3、然后上上层,就是找到【Intermediates.noindex】->【Adorawe.build】->【Release-iphoneos】(选择对应运行模式的)
->【Adorawe.build】->【Adorawe-LinkMap-normal-arm64.txt】
查看一下# Symbols:下排列顺序,以及[AppDelegate application:didFinishLaunchingWithOptions:]大体位置;
符号顺序明显是按照 Compile Sources 的文件顺序来排列的
测试调整:
如一个控制器里创建三个方法,test1,test2,test3;
编译运行,得到到的顺序会是
-[ViewController test1]
-[ViewController test2]
-[ViewController test3]
手动调整顺序:创建一个文件,如testOrder.txt
填写如下内容:
-[ViewController test3]
-[ViewController test2]
-[ViewController test1]
将testOrder.txt文件拖入到项目里,
修改Xcode配置:【Builde Settings】->【Order File】 -【textOrder文件路径(一般(./textOrder.txt);
Clean编译运行,再次按顺序去查看【xxx.txt】文件里顺序是否调整:
结果顺序
-[ViewController test3]
-[ViewController test2]
-[ViewController test1]
使用Clang插桩方式测试
clang
的插桩覆盖的官方文档如下 : clang 自带代码覆盖工具 文档中有详细概述
一般流程:
1、配置Xcode:【Builde Settings】->【Other C Flages】->【-fsanitize-coverage=func,trace-pc-guard】
2、在首页控制器里HomeViewController.m添加方法
头部引入
#import
#import
//原子队列 1、先进后出 2、线程安全 3、只能保存结构体
static OSQueueHead symbolList = OS_ATOMIC_QUEUE_INIT;
//定义符号结构体
typedef struct {
void *pc;
void *next;//下一个数据的结构体指针地址
}SYNode;
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.
}
void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
// if (!*guard) return; // Duplicate the guard check.
// 汇编一个函数执行完返回会将下一个要执行的函数地址给保存到 x30 寄存器中,将返回值给下一个函数。
// 所以这个函数的命名就是 返回 内存地址。 这里PC 就是拿到的内存地址
void *PC = __builtin_return_address(0);
SYNode * node = malloc(sizeof(SYNode));
*node = (SYNode){PC,NULL};
// 进入 入栈
// 最后一个参数是下一个数据的位置,也就是往上边的*node 的第二位插入
// offsetof(SYNode, next) next 成员在 结构体 SYNode 中的偏移值
OSAtomicEnqueue(&symbolList, node, offsetof(SYNode, next));
}
- (void)timeFilePath {
NSMutableArray * symbolNames = [NSMutableArray array];
while (YES) {
SYNode * node = OSAtomicDequeue(&symbolList, offsetof(SYNode, 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];//c函数前面带下划线
[symbolNames addObject:symbolName];
printf("%s \n",info.dli_sname);
}
// symbolNames = [[symbolNames reverseObjectEnumerator] allObjects];//取反
NSEnumerator * emt = [symbolNames reverseObjectEnumerator];
NSMutableArray* funcs = [NSMutableArray arrayWithCapacity:symbolNames.count];
NSString * name;
while (name = [emt nextObject]) {
if (![funcs containsObject:name]) {
[funcs addObject:name];
}
}
// 删掉当前方法(因为这个点击方法不是必须的)
[funcs removeObject:[NSString stringWithFormat:@"%s",__FUNCTION__]];
NSString * funcStr = [funcs componentsJoinedByString:@"\n"];
NSString * filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"liujilou.order"];
NSData * fileContents = [funcStr dataUsingEncoding:NSUTF8StringEncoding];
// 在路径上创建文件
[[NSFileManager defaultManager] createFileAtPath:filePath contents:fileContents attributes:nil];
STLLog(@"=====MMMMMMMM%@",filePath);
}
3、真机运行,当首页显示后,手动点击触发方法【timeFilePath】
4、导出生成的文件
Xcode:【Window】->【Devices and Simulators】->【选择自己手机中INSTALLED APPS列表的对应项目】->[+-符号旁边的设置符号】->【Download ...】下载到桌面;
5、右键显示包内容:【AppData】->【tmp】->【liujilou.order】;
6、可以打开liujilou.order查看一下顺序;
7、liujilou.order拖入到项目里;
8、修改Xcode配置:【Builde Settings】->【Order File】 -【liujilou.order文件路径(一般(./liujilou.order);
查看时间相关
Xcode配置:
DYLD_PRINT_STATISTICS_DETAILS 1,
DYLD_PRINT_STATISTICS 1
或instruments 【App Launch】、【System Trace】
使用Instruments - App Launch查看启动问题
iOS进阶专项分析(八)、深入App启动之dyld、map_images、load_images