启动优化的原理以及操作

2022-01-13  本文已影响0人  Harry__Li

首先我们要知道,启动是分为冷启动和热启动的。启动优化主要就是优化冷启动的时间。
冷启动又可以分为两个部分:pre_main阶段和main函数之后。

pre_main阶段:main函数之前,系统加载可执行文件到内存,执行一系列的加载链接等操作。dyld的加载过程。
main函数之后:从main函数开始,到构建第一个见面,渲染完成。

main函数之前

在优化main函数之前的加载过程之前,我们是不是首先要看看他的耗时。具体怎么怎么加载,然后我们再从这些方面入手。

镜像

我们首先要明白,每个app都是以images为单位进行加载的。而镜像的类型包括:

Mach-O

刚开始不知道这是个啥玩意,后来查了一些资料博客才明白。
Mach-O:是一种用于记录可执行文件、对象代码、动态加载代码和内存转存的文件格式。app生成的二进制可执行文件就是Mach-O格式的。ios所有的类编译后都会生成对应的目标文件.o文件,而这个可执行文件就是这些.o文件集合。

Mach-O 文件主要由三部分组成:

dylib

后缀名为.dylib的文件就是动态库。动态库是运行时加载的,可以背多个app公用(系统的动态库)。
这里动态库又分为了两种:系统的dylib和内嵌dylib(也就是我们自己引入的);

dyld

dyld:Dynamic Link Editor,看英文就可以理解出来,它是动态链接器。它是专门用来加载dylib文件的。

上面是一些我们需要知道的知识点。下面来详细说明启动的过程。

参考流程图我们知道,启动应用时,系统会通过fork()创建一个进程。然后执行镜像通过exec() 来替换为另一个可执行程序。然后执行如下的操作
1.把可执行文件加载到内存空间,从可执行文件中能够分析出dyld的路径。
2.把dyld加载到内存。
3.Load Dylibs:(1)、分析app依赖的所有dylib动态库(2)找到dylib对应的mach-o文件(3)打开、读取这些mach-o文件,并验证其有效性。(4)在系统内核中注册代码签名
4.Rebase/Binding指针重定位:
在dylib加载的过程中,系统为了安全考虑,引入了ASLR技术和代码签名。由于ASLR的存在,镜像会在新的随机地址上加载,和之前指针指向的地址会有一个偏差。所以,指针数量越少,指针修复的耗时也越少。
5.ObjC Setup
(1)dyld会注册所有声明过的objc类。
(2)将分类插入到类的方法列表中
(3)检查每个selector的唯一性。
6.Initializers和load:开始动态调整,往堆和栈中写入内容
(1)调用每个 Objc 类和分类中的 +load 方法
(2)调用 C/C++ 中的构造器函数(用 attribute((constructor)) 修饰的函数)
7.main() 的初始化。

pre_main优化操作

既然明白了main函数之前的操作过程,那么我们针对他的每一个过程就可以来优化

dyld
Rebase/Binding

这个过程是dyld调整修复地址,所以指针越少,耗时就越少。

Initializers

main函数阶段

查看main函数阶段的耗时

1.https://github.com/beiliao-mobile/BLStopwatch 创建了一个单例类,然后把每次的时间都加入到数组中。具体的操作可以查看git
2.使用xcode自带的。
Xcode → Open Developer Tool → Instruments → Time Profiler。
1.配置 Scheme。点击 Edit Scheme 找到 Profile 下的 Build Configuration,设置为 Debug。

  1. 配置 PROJECT。点击 PROJECT,在 Build Settings 中直接搜 Debug Information Format,把 Debug 对应的值改为 DWARF with dSYM File。
    3.启动Time Profiler。上选择Call Tree 中的 Separate Thread 和 Hide System Libraries。然后就可以查看启动时间。
启动优化

关于app的初始化,除了统计、日志这种必须要在app一启动就配置的事件,有一些配置也可以考虑延迟。可以从下面的一些角度做优化:

上一篇下一篇

猜你喜欢

热点阅读