iOS App启动优化(二)

这篇文章简单讲一下启动优化的二进制重排

应用程序在运行时,使用的是虚拟内存与物理内存相结合的方法加载数据的;虚拟内存是分页管理的,当使用到某一页虚拟内存的数据时,需要将对应的真实数据加载到物理内存中,将虚拟内存与物理内存之间形成一个映射关系,这个操作称为缺页异常(page fault),并且这个操作是需耗时的。原理网上很多大神都有讲解,我就不多做解释,直接手把手教大家怎么做。

第一步:通过Clang插桩获取app启动时调用了哪些方法,生成hank.order文件

1、在项目工程的如下位置添加-fsanitize-coverage=func,trace-pc-guard的编绎设置的标记:

2、创建一个工具类ClangHookFuncTool

ClangHookFuncTool.h代码

@interface ClangHookFuncTool : NSObject
+(NSString *)getClangHookFuncsListFilePath;
@end

ClangHookFuncTool.m代码 


#import "ClangHookFuncTool.h"
#import <dlfcn.h>
#import <libkern/OSAtomic.h>

@implementation ClangHookFuncTool
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 symbolList = OS_ATOMIC_QUEUE_INIT;
//定义符号结构体
typedef struct {
    void *pc;
    void *next;
}SYNode;

void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
//    if (!*guard) return;  // Duplicate the guard check.
    /*  精确定位 哪里开始 到哪里结束!  在这里面做判断写条件!*/
    
    void *PC = __builtin_return_address(0);
    SYNode *node = malloc(sizeof(SYNode));
    *node = (SYNode){PC,NULL};
    //进入
    OSAtomicEnqueue(&symbolList, node, offsetof(SYNode, next));
    
}


+(NSString *)getClangHookFuncsListFilePath{
    
    NSMutableArray <NSString *> * symbolNames = [NSMutableArray array];

    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);
        BOOL  isObjc = [name hasPrefix:@"+["] || [name hasPrefix:@"-["];
        NSString * symbolName = isObjc ? name: [@"_" stringByAppendingString:name];
        [symbolNames addObject:symbolName];
    }
    //取反
    NSEnumerator * emt = [symbolNames reverseObjectEnumerator];
    //去重
    NSMutableArray<NSString *> *funcs = [NSMutableArray arrayWithCapacity:symbolNames.count];
    NSString * name;
    while (name = [emt nextObject]) {
        if (![funcs containsObject:name]) {
            [funcs addObject:name];
        }
    }
    //干掉自己!
    [funcs removeObject:[NSString stringWithFormat:@"%s",__FUNCTION__]];
    //将数组变成字符串
    NSString * funcStr = [funcs  componentsJoinedByString:@"\n"];
    
    NSString * filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"hank.order"];
    NSData * fileContents = [funcStr dataUsingEncoding:NSUTF8StringEncoding];
    [[NSFileManager defaultManager] createFileAtPath:filePath contents:fileContents attributes:nil];
    NSLog(@"%@",funcStr);
    return filePath;
}
@end

3、在你app的进入后首页面控制器的viewDidLoad里面调用getClangHookFuncsListFilePath方法

[ClangHookFuncTool getClangHookFuncsListFilePath];

4、链接真机,clean项目,建议删掉真机上的app,然后运行 ,可以断点看上面的方法是否调用

5、获取hank.order文件

 打开xcode工程->Window->Devices And Simulators ->选中对应的工程 ->点击工程列表下的“齿轮”图标->Download Continaer,选择一个下载地址,右键下载下来的文件后显示包内容,到tmp文件夹中找到对应的hank.order文件. 

第二步:将hank.order文件引入

1、获取的hank.order文件放在项目根目录下

2、引用文件

第三步:搞定收工

去看看pre-main time时间,我这边亲测是减少了15%左右,每个app肯定不一样,快点去优化你的app吧!如果不知道怎么看pre-main time时间的,请移步我的另一篇文章iOS App启动优化(一)

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值