iOS app启动优化

Posted WeaterMr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS app启动优化相关的知识,希望对你有一定的参考价值。

二进制重排数据收集

1.Xcode 可以监测到 main 函数之前耗时时间。
通过添加环境变量可以打印app的启动时间分析(Edit scheme - run- arguments - Environment Variables
main 函数之前的开启时间
DYLD_PRINT_STATISTICS 设置为1
详细的开启时间
DYLD_PRINT_STATISTICS_DETAILS
400毫秒以内属于正常

  • dylib loading time:动态库载入耗时;
  • rebase/binding time:重定位、重绑定;
  • ObjC setup time:OC类注册(OC是一个动态语言,读取二进制的data内容,找到OC的相关的信息,注册OC类;OC的runtime需要维护一张映射表(sel 和 imp 的映射, 类与类名的全局表, 加载mach-O的时候,所有的类都需要加载到全局表中));
  • initializer time:执行load、构造函数耗时;

2.打开instrament 工具 点击System Trace 工具 。点击左上角的红色运行按钮,当应用程序显示第一个页面关闭。并在target栏中搜索Main Thead 找到当前的应用。

3.Build seting -->Linking -->Wright Link Map File 设为yes。
到对应的路径下找到启动时函数调用的一个.text 文档。

二进制原理与分析

虚拟内存的概念:
为了解决内存不足与安全方面的问题,诞生了虚拟内存。每个应用程序都有4G大小的虚拟内存空间,当需要加载应用程序时,操作系统通过每个对应应用的文件偏移量,按需装载到内存中。为了提高效率以分页的形式装载到内存中(在ios系统中 是 16K , Mac 中是 4K)。这样起到隔离每个应用程序的作用。
由于按需加载,当应用程序使用到某个模块就会加载对应的模块,这个时候系统会抱缺页中断,停止用户操作系统将缺失的叶加载到内存中,并且系统也可以通过计算不活跃的页惊醒覆盖。
当我们启动的时候会有大量的缺页中断,所以虽然一个缺页中短时间很短,用户基本无感知,但是成百上千的缺页中段将有视觉上的观感。二进制重拍的原理是解决不必要的缺页中断,通过进行方法重新排列减少缺页中断的数量。

Clang插桩

添加Clang插桩标记
搜索:Other C Flags
添加编译参数:-fsanitize-coverage=func,trace-pc-guard
运行报错添加对应的两个函数的对应实现,并自定义方法写入文件。

#include <stdint.h>
#include <stdio.h>
#include <sanitizer/coverage_interface.h>
#import <dlfcn.h>
#import <libkern/OSAtomic.h>

//定义原子队列
static OSQueueHead symbolList = OS_ATOMIC_QUEUE_INIT;
//定义符号结构体
typedef struct {
    void * pc;
    void * next;
} SYNode;



//里面反应了项目中符号的个数!!
void __sanitizer_cov_trace_pc_guard_init(uint32_t *start,
                                                    uint32_t *stop) {
  static uint64_t N;
  if (start == stop || *start) return;
//  printf("INIT: %p %p\\n", start, stop);
  for (uint32_t *x = start; x < stop; x++)
    *x = ++N;
}


//HOOK一切的回调函数!!
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)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //定义数组
    NSMutableArray<NSString *> * symbleNames = [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];
        [symbleNames addObject:symbolName];
          
    }
    //反向遍历数组

    NSEnumerator * em = [symbleNames reverseObjectEnumerator];
    NSMutableArray * funcs = [NSMutableArray arrayWithCapacity:symbleNames.count];
    NSString * name;
    while (name = [em nextObject]) {
        if (![funcs containsObject:name]) {//数组没有name
            [funcs addObject:name];
        }
    }
    //去掉自己!
    [funcs removeObject:[NSString stringWithFormat:@"%s",__func__]];
    
    //写入文件
    //1.编程字符串
    NSString * funcStr = [funcs componentsJoinedByString:@"\\n"];
    NSString * filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"hank.order"];
    NSData * file = [funcStr dataUsingEncoding:NSUTF8StringEncoding];
    
    [[NSFileManager defaultManager] createFileAtPath:filePath contents:file attributes:nil];
    
    NSLog(@"%@",funcStr);
}

配置二进制重排order文件

在对应的路径下找到我们生产的order文件,并且拷贝到工程目录第一层文件夹下,不是引用到工程
在Link 下找到 order file 将路径填写进去。

这时从新启动项目通过上面的第一步方式查看order重拍是否起效。
注意:

  • 1.在拿到order文件后将对应的插桩配置清除。
  • 2.无法监听到framework中的方法。只能监听到自己写的所有方法,函数。
  • 3.注意冷热启动带来的测试影响。

渲染优化

  • 1.cup和GPU
    cpu主要是用来各种计算,解码,GPU主要是通过计算好的数据进行屏幕渲染,也就是屏幕上显示的所用东西,都是通过GPU渲染出来的。
    渲染后,将其放到帧缓存区中,iOS 的帧缓存区是双缓冲机制,有前针缓存,后针缓存。
  • 2.image的处理,对于【uiimage imagewithname:】方法起时有一步隐藏的炒作,就是对image二进制数据进行解码操作,然后在现实到屏幕上
  • 3.离屏渲染
    圆角的设计,可以使用coreGraphics绘制裁剪圆角。

卡顿监控

1.耗电相关的主要来源 cpu,网络,定位,渲染
断点续传
如果仅仅只使用定位可以使用系统的框架,CllocationManager 的快速定位。 requestLocation

启动加载优化

  • 1.减少动态库,合并动态库
  • 2.定期清理不必要的类,分类
  • 3.减少c++虚函数的数量
  • 4.swift尽量使用struct
  • 5.initialize 和 dispatch_once 取代 +load
  • 6.main函数后尽量做一些延时处理。按需加载

安装包瘦身

安装包主要由可执行文件,资源组成
1.资源质量处理
2.去除没有用到的资源:https://github.com/tinymind/LSUnusedResources
可执行文件的瘦身
1.编译器优化,开启strip Linked
2.对一些没有用过的类进行清理,https://www.jetbrains.com/objc/ 检测未使用的代码:菜单栏-code-InspectCode (收费)
推荐:
数据结构与算法: 「严蔚敏」《数据结构》 《大话数据结构与算法》
网络层 《http权威指南》《TCP/IP详解卷1:协议》
架构与设计模式

以上是关于iOS app启动优化的主要内容,如果未能解决你的问题,请参考以下文章

iOS进阶 - App启动优化

iOS app启动优化

iOS app启动优化

iOS app启动优化

iOS APP性能优化

如何实现 iOS App 的冷启动优化