我爱普洱茶 发表于 2025-1-12 05:29:42

iOS App冷启动优化:二进制重排

原理

           二进制文件中方法的加载次序, 取决于方法在代码文件中的书写次序,而不是调用次序。 应用程序启动时会调用到的方法是有限的,但大概分散在许多个。由于内存是分页管理的,要加载就要整页加载。这就导致许多完全还用不到的方法,会在应用启动时就会被加载到内存,这必要开辟大量内存页,进而增加大量启动耗时。            如果将BeforeMain阶段用到的方法都找出来出来,让他们在同一或相近的内存页中次序提前加载,就可以大大减少应用启动时缺页异常出现的概率。
技能要点

     (1)罗列出应用启动时会调用到的方法,将其保存到.order文件中
        可行的方案是Clang插桩:
        https://i-blog.csdnimg.cn/blog_migrate/f337db1ddebab374b180d23fb1a553be.png
        起首,我们在项目的Build Settings中搜索并设置 Other C Flags/ Other C++ Flags 为 -fsanitize-coverage=func,trace-pc-guard。如果有swift代码,必要设置 Other Swift Flags 设置为 **** -sanitize-coverage=func -sanitize=undefined, 这样应用启动时全部方法都的边沿都被插入了__sanitizer_cov_trace_pc_guard(...)方法的调用。
        然后, 我们只必要实现__sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop)方法, 然后使用dladdr()方法, 就可以将被调用的方法信息罗列出来,然后将其写入.order文件中即可 。                
//原子队列
staticOSQueueHead symbolList = OS_ATOMIC_QUEUE_INIT;
//定义符号结构体
typedef struct {
    void *pc;
    void *next;
}SYNode;

- (void)viewDidLoad {
    ;

    ;
}
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 __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
    void *PC = __builtin_return_address(0);
    SYNode *node = malloc(sizeof(SYNode));
    *node = (SYNode){PC,NULL};
    //写入队列
    OSAtomicEnqueue(&symbolList, node, offsetof(SYNode, next));
}
// 解析队列并生成.order文件
- (void) genrateOrderFile{
    NSMutableArray <NSString *> * symbolNames = ;
    while (YES) {
      SYNode * node = OSAtomicDequeue(&symbolList, offsetof(SYNode, next));
      if (node == NULL) {
            break;
      }
      Dl_info info;
      dladdr(node->pc, &info);
      NSString * name = @(info.dli_sname);
      BOOLisObjc = || ;
      NSString * symbolName = isObjc ? name: [@"_" stringByAppendingString:name];
      ;
    }
    //取反
    NSEnumerator * enumerator = ;
    //去重
    NSMutableArray<NSString *> *funcs = ;
    NSString * name;
    while (name = ) {
      if (!) {
            ;
      }
    }
    ];
   
    //写入.order文件
    NSString * funcStr = ;
    NSString * filePath = ;
    NSData * fileContents = ;
    [ createFileAtPath:filePath contents:fileContents attributes:nil];
    NSLog(@"%@",funcStr);
}
@end        (2)设置应用在链接时, 根据.order文件次序加载其中的符号
          只需在项目的Build Settings中搜索“Order File”,配置.order文件即可   
         https://i-blog.csdnimg.cn/blog_migrate/63214b21dc5743f36cbeb0a444378d39.png

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: iOS App冷启动优化:二进制重排