APP一般分为热启动和冷启动
- 冷启动是指APP点击启动前,它的进程不在系统里,需要系统创建新的进程分配给它启动,这是一次完成的启动过程。
- 热启动是指APP在冷启动之后用户将APP退出,挂在后台,此时它的进程还是存在在系统的进程里,用户在此启动需要的时间比较少,可以做的事情不多。
这里只做冷启动的优化。
首先我们要知道App在启动时都干了些什么事,才能有针对的进行优化。 App的启动可以归纳为三个阶段:
main()
函数执行前main()
函数执行后- 首屏渲染完成
main()函数执行前
在main()函数执行前,系统主要会做以下几件事:
- 加载可执行文件(APP的.o文件集合)
- 加载动态连结库,进行rebase指针调整和bind符号绑定
- Objc运行时的初始处理,包括objc相关类的注册,category注册,selector唯一性检查等
- 初始化,包括了+load()方法的执行,attribute((constructor)) 修饰的函数的调用,创建C++静态全局变量
相应的这个阶段对于启动速度优化可以做的事情:
- 减少动态库的加载
- 减少加载启动后不会使用的类或者方法
- +load()方法里的内容可以放在首屏渲染完成后在去处理,或者使用+initialize()方法替换
- 控制C++全局变量的数量
main()函授执行后
main()执行后的阶段是指,从main()执行开始到appDelegate的didFinishLaunchingWithOptions方法里首屏渲染相关方法执行完成。
- 首屏初始化所需配置文件的读写操作
- 首屏列表大数据的读取
- 首屏渲染的大量计算
这里更加优化的开发方式是确定哪些是首屏渲染必要的初始化功能,哪些是APP启动必要的初始化功能,而那些只是需要在对应的功能开始是才需要初始化的。整理出来之后,分别放到对应的阶段进行初始化
首屏渲染完成后
这个阶段就是从渲染完成时开始,到didFinishLaunchingWithOptions 方法作用域结束时结束。 这个阶段用户已经可以看到App的首页信息了,所以优化级别放在最后,但是耗时操作还是要优先处理,以免影响用户体验。
功能级别的启动优化
从main()函数执行后这个阶段下手,优化的思路是main()函数执行后到首屏渲染完成前只处理与首屏渲染相关的操作,非首屏业务的初始化,监听注册,配置文件读取等放到首屏渲染完层后处理。
方法级别的优化
检查首屏渲染完成前主线程上有哪些耗时方法,将没必要的耗时方法之后或者异步执行。通常情况下,耗时较长的方法主要发生在计算大量数据的情况下,具体表现就是加载,编辑,存储图片和文件等资源。 这里有两种方式可以可以监控App启动速度:
- 定时抓取主线程上方法的调用堆栈,计算一段时间里方法的耗时
- 对objc_msgSend方法进行hook操作,来掌握所有方法的耗时