「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战」。
启动优化
-
启动时间:从用户点击app图标开始到 AppDelegate 的didFinishLaunching
-
冷启动: 内存中不包含app相关数据的启动,一般我们可以通过重启手机来实现冷启动
- 热启动: 是指杀掉app进程后,数据仍然存在时的启动
-
启动优化 -> T1 + T2 需要启动优化的部分
- T1: pre-main阶段, 即main函数之前, 操作系统加载APP可执行文件到内存,执行一系列加载&链接等工作 -> dyld加载过程.
- main函数之后, 即从main函数开始, 到Appdelegate到didFinishLaunching方法执行完成为止, 主要是构建第一个界面,并完成渲染.
main函数之前的部分
Edit Scheme -> Run -> Arguments -> Environment Variables -> 添加'DYLD_PRINT_STATISTICS'设为1
pre-main字段说明
-
dylib loading time(动态库耗时)
-
rebase/binding time(偏移修正/符号绑定耗时)
- rebase(偏移修正):任何一个app生成的二进制文件,在二进制文件内部所有的方法、函数调用,都有一个地址,这个地址是在当前二进制文件中的偏移地址。一旦在运行时刻(即运行到内存中),每次系统都会随机分配一个ASLR(Address Space Layout Randomization,地址空间布局随机化)地址值(是一个安全机制,会分配一个随机的数值,插入在二进制文件的开头),例如,二进制文件中有一个 test方法,偏移值是0x0001,而随机分配的ASLR是0x1f00,如果想访问test方法,其内存地址(即真实地址)变为 ASLR+偏移值 = 运行时确定的内存地址(即0x1f00+0x0001 = 0x1f01)
- binding(绑定):,例如NSLog方法,在编译时期生成的mach-o文件中,会创建一个符号!NSLog(目前指向一个随机的地址),然后在运行时(从磁盘加载到内存中,是一个镜像文件),会将真正的地址给符号(即在内存中将地址与符号进行绑定,是dyld做的,也称为动态库符号绑定),一句话概括:绑定就是给符号赋值的过程
-
ObjC setup time (OC类注册的耗时):OC类越多,越耗时
-
initializer time(执行load和构造函数的耗时)
优化建议:
- 尽量少用外部动态库,苹果官方建议自定义的动态库最好不要超过6个,如果超过6个,需要合并动态库
- OC类越多越耗时
- 将不必须在+load方法中做的事情延迟到+initialize中,尽量不要用C++虚函数
- 如果是swift,尽量使用struct
main函数阶段的优化
didFinishLaunching方法中,主要是执行了各种业务,有很多并不是必须在这里立即执行的,这种业务我们可以采取延迟加载,防止影响启动时间。
didFinishLaunching中业务主要类型
- 【第一类】初始化第三方sdk
- 【第二类】app运行环境配置
- 【第三类】自己工具类的初始化等