APP启动速度优化与监护
冷启动:APP启动前,它的进程不在系统里,需要系统新创建一个进程分配给它启动的情况。这是一次完整的启动过程。
热启动: APP在冷启动后用户将APP退到后台,在APP进程还在系统里的情况下,用户重新启动进入APP的过程,这个过程做的事情非常少。
APP的启动主要包括三个方面:main函数执行前,main函数执行后,首屏渲染完成后
mian()函数执行前,系统需要做的事情:
- 加载可执行文件(app的.o文件的集合)
- 加载动态链接库,进行release指针调整和bind符号绑定
- Objc运行时的初始处理,包括Objc相关类的注册、category注册、selector唯一性检查等
- 初始化,包括了执行load()方法、attribute((constructor)) 修饰的函数的调用、创建 C++ 静态全局变量。
这个阶段对于启动速度优化来说,可以做的事情包括:
- 减少动态库加载。
- 减少加载启动后不会去使用的类或者方法
- +load()的方法里的内容可以放到首屏渲染完成后再执行,或使用+initialize()方法替换掉。因为在一个load()方法里,进行运行时方法替换操作会带来4毫秒的消耗。
- 控制C++全局变量的数量
总结一下:app的启动由dyld主导,将可执行文件加载到内存,顺便加载所有依赖的动态库;并由runtime负责加载成objc定义的结构;所有初始化工作结束后,dyld会调用main函数;接下来就是UIApplicationMain函数,AppDelegate的didFinishLauchingWithOptions方法
main() 函数执行后
main函数执行后的阶段,指的是从main函数执行开始,到appDelegate的didFinishLaunchingWithOptions方法里首屏渲染相关方法执行完成。
首页的业务代码都在这个阶段,也就是首屏渲染前执行的
主要包括:
- 首屏初始化所需配置文件的读写操作
- 首屏列表大数据的读取
- 首屏渲染的大量计算等
这个阶段的优化:
从功能上梳理出哪些是首屏渲染必要的初始化功能,哪些是app启动必要的初始化功能,而哪些是需要在对应功能开始使用时才初始化的。梳理完之后,将这些初始化功能分别放到合适的阶段进行
首屏渲染完成后
<u>首屏渲染完成后的这个阶段,主要完成的是,非首屏其他业务服务模块的初始化、监听的注册、配置文件的读取等。从函数上来看指的是,截止到didFinishLaunchingWithOptions方法作用域内执行首屏渲染之后的所有方法执行完成。简单说的话,这个阶段是从渲染完成时开始,到didFinishLaunchingWithOptions方法作用域结束时结束。</u>
这个阶段的优化:
功能级别的启动优化(就是要从main函数执行后这个阶段下手)
优化思路:main函数开始执行后到首屏渲染完成前只处理首屏渲染相关的业务,其他非首屏业务的初始化、监听注册、配置文件读取等都放到首屏渲染完成后去做
- 方法级别的启动优化:
检查首屏渲染完成前主线程上有哪些耗时方法,将没必要的耗时方法滞后或者异步执行。通常情况下,耗时较长的方法主要发生在计算大量数据的情况下,具体的表现就是加载、编辑、存储图片和文件资源等
启动速度的监控:
- 定时抓取主线程上的方法调用堆栈,计算一段时间里各个方法的耗时(最好设置为0.01秒)(Time Profiler)
- 对objc_send()方法进行hook来掌握所有方法的执行耗时(推荐)。