分支:zebra_v.2.7.2_xiaopu
測試機信息:8P手機 iOS13.3.1 未越獄(越獄會加載mobilesubrstrate動態(tài)庫很耗時) 正式環(huán)境 無權(quán)限認(rèn)證提示 無首次引導(dǎo)圖 wifi
Xcode Version:11.3.1
一、 測試重排前的缺頁異常次數(shù)和pre-main時間
手機環(huán)境準(zhǔn)備
測試過程中發(fā)現(xiàn)6s、8P會在重啟后偶爾后臺還會有之前的進程。為了避免影響,每次測試前,殺掉后臺所有進程,再重啟手機,確保APP真正處于冷啟動。-
Xcode測試流程
首先Xcode跑對應(yīng)項目到手機上,然后每次殺后臺,重啟,打開Xcode選中 Open Developer Tool 的Instruments面板,選擇System Trace,選擇真機設(shè)備,點擊運行按鈕,等待首頁出現(xiàn)點擊?停止,等待分析完成。
刪除過濾條件,直接輸入main,找到項目的target箭頭展開,點擊Main thread,
根據(jù)圖中選擇Virtual Memory 查看 File Backed Page In次數(shù).
Pasted Graphic 13.png -
重排前5次的缺頁異常(Page Fault)測試數(shù)據(jù)如下
image.png
image.png
image.png
image.png
image.png -
修改配置,在Xcode控制臺輸出pre-main
image.png -
每次殺進程,重啟,Xcode運行,控制臺打印結(jié)果
pre-main time 1.2 seconds (100.0;.png
Total pre-main time 1.1 seconds (100.0).png
Total pre-main time 1.1 seconds (100.0).png
pre-main time 1.1 seconds (100.0).png
Total pre-main time 1.2 seconds (100.0).png
二、輸出項目啟動的Orderfile,注意代碼放置的位置,會影響最后生成的Orderfile大小,也會影響重排后缺頁異常的次數(shù)。
參考源碼如下
#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函數(shù)");
}
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 就是針對某個結(jié)構(gòu)體找到某個屬性相對這個結(jié)構(gòu)體的偏移量
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);
//將結(jié)果寫入到文件
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;
//定義符號結(jié)構(gòu)體
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 用在這里是為了入隊添加下一個節(jié)點找到 前一個節(jié)點next指針的位置
OSAtomicEnqueue(&symboList, node, offsetof(SymbolNode, next));
}
@end
cocoapod 工程問題
對于 cocoapod 工程引入的庫 , 由于針對不同的 target . 那么我們在主程序中的 target 添加的編譯設(shè)置 Write Link Map File , -fsanitize-coverage=func,trace-pc-guard 以及 order file 等設(shè)置肯定是不會生效的 . 解決方法就是針對需要的 target 去做對應(yīng)的設(shè)置即可 .-
將生成的orderfile文件配置放到工程根目錄下,并在xcode配置Order File
image.png
三、重復(fù)步驟一的流程,測試數(shù)據(jù) 建議先Clean一下工程。












