从点击图标启动程序到didFinishLaunchingWithOptions首页viewDidLoad加载完成,是一次完整的启动过程。
从后台从新进入前台
按照main调用之前和之后可以分为两个个阶段:
- T1:pre-main阶段,即main()函数之前,即操作系统加载App可执行文件到内存,然后执行一系列的加载&链接等工作,最后执行至App的main()函数;
- T2:main()函数之后,即从main()开始,到appDelegate的didFinishLaunchingWithOptions方法执行完毕前这段时间,主要是构建第一个界面,并完成渲染。
分析两个阶段都做了什么操作才能有针对的优化
苹果提供了内建的测量方法,在 Xcode 中 Edit scheme -> Run -> Auguments 将环境变量 DYLD_PRINT_STATISTICS
设为 1。
也可以用instrument
的Time profile
另一种方法:
配置Build Options—>Debug Information Format的debug模式下选择DRAF with dSYM File
Edit Scheme—>profile—>Build Configuration选择debug
command + i启动instrument,选择Time profile查看运行时间
Total pre-main time: 521.18 milliseconds (100.0%)
dylib loading time: 28.46 milliseconds (5.4%)
rebase/binding time: 186.65 milliseconds (35.8%)
ObjC setup time: 241.89 milliseconds (46.4%)
initializer time: 64.16 milliseconds (12.3%)
slowest intializers :
libSystem.B.dylib : 9.33 milliseconds (1.7%)
libBacktraceRecording.dylib : 11.79 milliseconds (2.2%)
libMainThreadChecker.dylib : 26.96 milliseconds (5.1%)
libViewDebuggerSupport.dylib : 13.69 milliseconds (2.6%)
程序启动总共用了521ms,以及各个阶段所用的时间、slowest intializers(最慢)的几个库所用的时间。
dylib loading(加载动态链接库)
- 优化的点
减少非系统库的依赖
合并非系统库
Rebase/Bind image 指针重定位
- 优化的点有
减少Objc类数量, 减少selector数量
减少C++虚函数数量
Objc setup
- 优化的点基本没有
initializer
- 优化的点有
减少过多的+load方法
检查 +load 方法,尽量把事情推迟到 +initiailize 方法里执行。
在这里我们修改了部分原本代码中直接在 +load 函数初始化逻辑改为在 +initialize 中加载,也就是到使用时才加载。
在didFinishLaunchingWithOptions
里面通常都是
- 日志、统计等必须在 APP 一启动就最先配置的事件
- 项目配置、环境配置、用户信息的初始化 、推送、IM等事件
- 根容器、控制器初始化
- 优化的点
多线程异步加载(sdk初始化异步操作)
优化业务逻辑
首页渲染(放到viewDidLoad之后操作)
纯代码代替xib/storyboard来进行UI框架的搭建