iOS項目二進制重排效果分析

分支: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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容