原理,代码执行是pagefault会消耗性能,将order file提供给编译器,让它按给到的顺序来链接.o,从而减少pagefault次数
https://mp.weixin.qq.com/s/Drmmx5JtjG3UtTFksL6Q8Q
https://www.jianshu.com/p/024b3d847fe0
https://www.lizenghai.com/archives/41858.html
如何获取启动时调用的那些方法(
sanitizerCoverage
)
https://blog.csdn.net/zhang14916/article/details/100924489
https://blog.csdn.net/chouju2014/article/details/100657380
出处:
配置:other c flag -fsanitize_coverage=func,trace_pc_guard
https://github.com/yulingtianxia/AppOrderFiles
//调用,直接停止统计并且写入到一个文件extern void AppOrderFiles(void(^completion)(NSString *orderFilePath));
//
// AppOrderFiles.m
// AppOrderFiles
//
// Created by 杨萧玉 on 2019/8/31.
// Copyright © 2019 杨萧玉. All rights reserved.
//
#import "AppOrderFiles.h"
#import <dlfcn.h>
#import <libkern/OSAtomicQueue.h>
#import <pthread.h>
static OSQueueHead queue = OS_ATOMIC_QUEUE_INIT;
static BOOL collectFinished = NO;
typedef struct {
void *pc;
void *next;
} PCNode;
// The guards are [start, stop).
// This function will be called at least once per DSO and may be called
// more than once with the same values of start/stop.
void __sanitizer_cov_trace_pc_guard_init(uint32_t *start,
uint32_t *stop) {
static uint32_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.
}
// This callback is inserted by the compiler on every edge in the
// control flow (some optimizations apply).
// Typically, the compiler will emit the code like this:
// if(*guard)
// __sanitizer_cov_trace_pc_guard(guard);
// But for large functions it will emit a simple call:
// __sanitizer_cov_trace_pc_guard(guard);
void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
if (!*guard) return; // Duplicate the guard check.
if (collectFinished) {
return;
}
// If you set *guard to 0 this code will not be called again for this edge.
// Now you can get the PC and do whatever you want:
// store it somewhere or symbolize it and print right away.
// The values of `*guard` are as you set them in
// __sanitizer_cov_trace_pc_guard_init and so you can make them consecutive
// and use them to dereference an array or a bit vector.
*guard = 0;
void *PC = __builtin_return_address(0);
PCNode *node = malloc(sizeof(PCNode));
*node = (PCNode){PC, NULL};
OSAtomicEnqueue(&queue, node, offsetof(PCNode, next));
}
extern void AppOrderFiles(void(^completion)(NSString *orderFilePath)) {
collectFinished = YES;
__sync_synchronize();
NSString *functionExclude = [NSString stringWithFormat:@"_%s", __FUNCTION__];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSMutableArray <NSString *> *functions = [NSMutableArray array];
while (YES) {
PCNode *node = OSAtomicDequeue(&queue, offsetof(PCNode, next));
if (node == NULL) {
break;
}
Dl_info info = {0};
dladdr(node->pc, &info);
NSString *name = @(info.dli_sname);
BOOL isObjc = [name hasPrefix:@"+["] || [name hasPrefix:@"-["];
NSString *symbolName = isObjc ? name : [@"_" stringByAppendingString:name];
[functions addObject:symbolName];
}
if (functions.count == 0) {
if (completion) {
completion(nil);
}
return;
}
NSMutableArray<NSString *> *calls = [NSMutableArray arrayWithCapacity:functions.count];
NSEnumerator *enumerator = [functions reverseObjectEnumerator];
NSString *obj;
while (obj = [enumerator nextObject]) {
if (![calls containsObject:obj]) {
[calls addObject:obj];
}
}
[calls removeObject:functionExclude];
NSString *result = [calls componentsJoinedByString:@"\n"];
NSLog(@"Order:\n%@", result);
NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"app.order"];
NSData *fileContents = [result dataUsingEncoding:NSUTF8StringEncoding];
BOOL success = [[NSFileManager defaultManager] createFileAtPath:filePath
contents:fileContents
attributes:nil];
if (completion) {
completion(success ? filePath : nil);
}
});
}
来源:https://www.cnblogs.com/yuxiaoyiyou/p/12214255.html