iOS App啓動優化(六):實用黨直接看這裏

iOS App啓動優化(一):檢測啓動時間node

iOS App啓動優化(二):物理內存和虛擬內存數組

iOS App啓動優化(三):二進制重排bash

iOS App啓動優化(四):編譯期插樁 && 獲取方法符號函數

iOS App啓動優化(五):收集符號 && 生成 Order Filepost

iOS App啓動優化(六):實用黨直接看這裏優化

效果對比

優化前 ui

優化後spa

步驟一:添加 Build Setting 設置

Target -> Build Setting -> Custom Complier Flags ->code

Other C Flags 添加component

  • -fsanitize-coverage=func,trace-pc-guard

Other Swift Flags 添加

  • -sanitize-coverage=func
  • -sanitize=undefined

步驟二:添加代碼

添加到啓動最先的那個 ViewController 便可。

#import "dlfcn.h"
#import <libkern/OSAtomic.h>
複製代碼
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.
}


//初始化原子隊列
static OSQueueHead list = OS_ATOMIC_QUEUE_INIT;
//定義節點結構體
typedef struct {
    void *pc;   //存下獲取到的PC
    void *next; //指向下一個節點
} Node;


void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
     void *PC = __builtin_return_address(0);
     Node *node = malloc(sizeof(Node));
     *node = (Node){PC, NULL};
     // offsetof() 計算出列尾,OSAtomicEnqueue() 把 node 加入 list 尾巴
     OSAtomicEnqueue(&list, node, offsetof(Node, next));
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
     NSMutableArray *arr = [NSMutableArray array];
     while(1){
         //有進就有出,這個方法和 OSAtomicEnqueue() 類比使用
         Node *node = OSAtomicDequeue(&list, offsetof(Node, next));
         //退出機制
         if (node == NULL) {
             break;
         }
         //獲取函數信息
         Dl_info info;
         dladdr(node->pc, &info);
         NSString *sname = [NSString stringWithCString:info.dli_sname encoding:NSUTF8StringEncoding];
         printf("%s \n", info.dli_sname);
         //處理c函數及block前綴
         BOOL isObjc = [sname hasPrefix:@"+["] || [sname hasPrefix:@"-["];
         //c函數及block須要在開頭添加下劃線
         sname = isObjc ? sname: [@"_" stringByAppendingString:sname];
         
         //去重
         if (![arr containsObject:sname]) {
             //由於入棧的時候是從上至下,取出的時候方向是從下至上,那麼就須要倒序,直接插在數組頭部便可
             [arr insertObject:sname atIndex:0];
         }
     }
       
     //去掉 touchesBegan 方法 啓動的時候不會掉用到這個
     [arr removeObject:[NSString stringWithFormat:@"%s",__FUNCTION__]];
     //將數組合成字符串
     NSString * funcStr = [arr  componentsJoinedByString:@"\n"];
     //寫入文件
     NSString * filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"link.order"];
     NSData * fileContents = [funcStr dataUsingEncoding:NSUTF8StringEncoding];
     NSLog(@"%@", filePath);
     [[NSFileManager defaultManager] createFileAtPath:filePath contents:fileContents attributes:nil];
}
複製代碼

步驟三:取出 order file

  • 在步驟二的代碼NSLog(@"%@", filePath); 斷點
  • 若是頁面沒法觸發點擊,viewDidLoad裏面調用touchesBegan:withEvent:也能夠
  • 運行代碼後記錄 link.order 的路徑
  • Finder 前往路徑取出 order file

步驟四:設置 order file

  • link.order 的路徑放到工程根目錄
  • Target -> Build Setting -> Linking -> Order File 設置路徑

步驟五:編譯代碼

  • 把步驟一 order file 的設置還原
  • 把步驟二添加代碼刪除
  • clean 之後編譯代碼
相關文章
相關標籤/搜索