分支:zebra_v.2.7.2_xiaopu
测试机信息:8P手机 iOS13.3.1 未越狱(越狱会加载mobilesubrstrate动态库很耗时) 正式环境 无权限认证提示 无首次引导图 wifi
Xcode Version:11.3.1
一、 测试重排前的缺页异常次数和pre-main时间
手机环境准备
测试过程中发现6s、8P会在重启后偶尔后台还会有之前的进程。为了避免影响,每次测试前,杀掉后台所有进程,再重启手机,确保APP真正处于冷启动。-
Xcode测试流程
首先Xcode跑对应项目到手机上,然后每次杀后台,重启,打开Xcode选中 Open Developer Tool 的Instruments面板,选择System Trace,选择真机设备,点击运行按钮,等待首页出现点击⏹停止,等待分析完成。
删除过滤条件,直接输入main,找到项目的target箭头展开,点击Main thread,
根据图中选择Virtual Memory 查看 File Backed Page In次数.
-
重排前5次的缺页异常(Page Fault)测试数据如下
-
修改配置,在Xcode控制台输出pre-main
-
每次杀进程,重启,Xcode运行,控制台打印结果
二、输出项目启动的Orderfile,注意代码放置的位置,会影响最后生成的Orderfile大小,也会影响重排后缺页异常的次数。
参考源码如下
#import "ViewController.h"
#import <dlfcn.h>
#import <libkern/OSAtomic.h>
@interface ViewController ()
@end
@implementation ViewController
+ (void)load{
}
- (void)viewDidLoad {
[super viewDidLoad];
testCFunc();
[self testOCFunc];
}
- (void)testOCFunc{
NSLog(@"oc函数");
}
void testCFunc(){
LBBlock();
}
void(^LBBlock)(void) = ^(void){
NSLog(@"block");
};
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)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
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];
}
}
//取反
NSArray * symbolAry = [[symbolNames reverseObjectEnumerator] allObjects];
NSLog(@"%@",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(@"%@",filePath);
}else{
NSLog(@"文件写入出错");
}
}
//原子队列
static OSQueueHead symboList = OS_ATOMIC_QUEUE_INIT;
//定义符号结构体
typedef struct{
void * pc;
void * next;
}SymbolNode;
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));
}
@end
cocoapod 工程问题
对于 cocoapod 工程引入的库 , 由于针对不同的 target . 那么我们在主程序中的 target 添加的编译设置 Write Link Map File , -fsanitize-coverage=func,trace-pc-guard 以及 order file 等设置肯定是不会生效的 . 解决方法就是针对需要的 target 去做对应的设置即可 .-
将生成的orderfile文件配置放到工程根目录下,并在xcode配置Order File
三、重复步骤一的流程,测试数据 建议先Clean一下工程。