ios APP启动优化

冷启动优化

更多的是业务层面的优化

发挥 cpu的价值,多开线程异步,让cpu达到最大价值

启动过程

Main 之前  —影响最大

(dyld 监控)耗时

动态库的加载 不超过4-6个

Main之后 基本上是业务层面

   Total pre-main time: 704.32 milliseconds (100.0%)              // 总共启动时间

         dylib loading time: 174.75 milliseconds (24.8%)              // 动态库加载时间

        rebase/binding time:  36.61 milliseconds (5.1%)                // 修复内部指针地址(ASLR 随机偏移值)/外部符号绑定(DYLD去做的)

            ObjC setup time: 170.39 milliseconds (24.1%)              // OC类注册的耗时时间

           initializer time: 322.29 milliseconds (45.7%)              // load 的时间 

           slowest intializers :                                //  启动最耗时的内容

             libSystem.B.dylib :  10.14 milliseconds (1.4%)                  // 系统库 

    libMainThreadChecker.dylib :  85.19 milliseconds (12.0%)                  //系统库 

                  (App名称) : 411.80 milliseconds (58.4%)                      // 主程序

在Main函数之前,有哪些是可以 做 优化的:

1、库的加载

系统库经过优化处理的,本身加载就 很快。

自己倒入的库: 苹果给出的建议是不超过6个。如果超过6个,可以采用合并的方式。

2、减少不必要的类 、资源图片等。

比如随着版本更新迭代,有些类、图片等被弃用了的。

可以使用工具检测没有用到的类

这个操作相对来说优化的成效不高。有人说 减少2w个类,启动时间只少了800 毫秒。

3、能不在Load里面做的操作,就不要在Load操作。

4、二进制重排

这个主要是正对binding阶段的操作。参考抖音ios团队的经验 

基于静态扫描+运行时trace的方案仍然存在少量瓶颈:

initialize hook不到

部分block hook不到

C++通过寄存器的间接函数调用静态扫描不出来

目前的重排方案能够覆盖到80%~90%的符号,未来我们会尝试编译期插桩等方案来进行100%的符号覆盖,让重排达到最优效果。

Main 之后的优化

1、能懒加载的就懒加载

2、发货CPU的性能(多线程初始化)

3、启动阶段的尽量不要用Xib、stroyboard。 Xib、storyboard都是需要进行xml解析,相对纯代码来讲,是比较耗时的。

2016 中首次出现了 App 启动优化的话题,其中提到:

App 启动最佳速度是400ms以内,因为从点击 App 图标启动,然后 Launch Screen 出现再消失的时间就是400ms;

App 启动最慢不得大于20s,否则进程会被系统杀死;(启动时间最好以 App 所支持的最低配置设备为准。)

指针重定位优化方案

减少 ObjC 类(class)、方法(selector)、分类(category)的数量,比如合并一些功能,删除无效的类、方法和分类等(可以借助AppCode的 Inspect Code 功能进行代码瘦身);

减少 C++ 虚函数;(虚函数会创建 vtable,这也会在 __DATA 段中创建结构。)

多用 Swift Structs。(因为 Swift Structs 是静态分发的,它的结构内部做了优化,符号数量更少。)

Initializers

优化方案

尽量避免在类的 +load 方法中初始化,可以推迟到 +initiailize 中进行;(因为在一个 +load 方法中进行运行时方法替换操作会带来 4ms 的消耗)

避免使用 __atribute__((constructor)) 将方法显式标记为初始化器,而是让初始化方法调用时再执行。比如用 dispatch_once()、pthread_once() 或 std::once(),相当于在第一次使用时才初始化,推迟了一部分工作耗时。:

减少非基本类型的 C++ 静态全局变量的个数。(因为这类全局变量通常是类或者结构体,如果在构造函数中有繁重的工作,就会拖慢启动速度

总结一下 pre-main 阶段可行的优化方案:

重新梳理架构,减少不必要的内置动态库数量

进行代码瘦身,合并或删除无效的ObjC类、Category、方法、C++ 静态全局变量等

将不必须在 +load 方法中执行的任务延迟到 +initialize 中

减少 C++ 虚函数

main 之后

启动优化

main() 被调用之后,didFinishLaunchingWithOptions 阶段,App 会进行必要的初始化操作,而 viewDidAppear 执行结束之前则是做了首页内容的加载和显示。

关于App 的初始化,除了统计、日志这种须要在 App 一启动就配置的事件,有一些配置也可以考虑延迟加载。如果你在 didFinishLaunchingWithOptions 中同时也涉及到了首屏的加载,那么可以考虑从这些角度优化:

用纯代码的方式,而不是 xib/Storyboard,来加载首页视图

延迟暂时不需要的二方/三方库加载;

延迟执行部分业务逻辑和 UI 配置;

延迟加载/懒加载部分视图;

避免首屏加载时大量的本地/网络数据读取;

在 release 包中移除 NSLog 打印;

在视觉可接受的范围内,压缩页面中的图片大小;

你可能感兴趣的:(ios APP启动优化)