APP性能优化之一 启动优化

今天来讲APP性能优化的第一步,也是用户接触最直接的一步:冷启动优化。主要从以下几个问题来入手

  • 什么是冷启动?什么是热启动?
  • 冷启动的过程中,系统都做了什么
  • pre-main过程该如何优化?
  • T3过程该如何优化?

什么是冷启动?什么是热启动?

冷启动:在APP点击启动前,他的进程不在系统中,需要系统新创建一个进程分配给它,并进行启动的情况。冷启动是一次完整的启动过程。
相对的
热启动:按下home键的时候,app还存在一段时间,这时点击app马上就能恢复到原状态,这种启动我们称为热启动。

APP的启动时间,是指从用户点击APP开始,到用户看到第一个界面之间的时间。总的来说,APP启动主要包括三个阶段:
1.T1: main()函数执行前:pre-main
2.T2: main()函数执行后至didFinishLaunch:behind-main
3.T3: didFinishLaunch至首屏渲染完成

冷启动的过程中,系统都做了什么

dyld是App的启动器,启动的大部分事情都由dyld完成,iOS的启动大致分为几个部分:

  1. 内核将App的执行文件加载到随机地址空间(加载到随机地址主要是因为ASLR技术)
  2. 内核将dyld的执行文件加载到随机地址空间
  3. 内核执行dyld文件
  4. dyld启动App
    1. dyld加载所有App所依赖的dylibs(动态库)
    2. 执行rebasing/binding修复地址
    3. Objc Setup
    4. initialize
  5. dyld调用App中的main(),将主动权交还给App

手机内核只负责将App的执行文件和dyld加载到内存中,然后所有的启动工作都交给了dyld。

冷启动的优化工作主要都是在上面的第四步里做文章,第四步的具体工作可以看下面这张图


dyld启动App工作内容

总结起来,pre-main()执行了如下操作

  • 加载可执行文件(App的.o文件集合)
  • 加载动态链接库,进行rebase指针调整和bind符号绑定
  • Objc运行时的初始处理,包括Objc相关类注册、category注册、selector唯一性检查等
  • 初始化调用,包括了执行+load()方法、attribute((constructor))修饰的函数的调用、创建C++静态全局变量。

pre-main过程该如何优化?

针对冷启动的优化,自然也是根据上面的相应的步骤进行优化

1 减少动态库的加载。

原则上尽量减少动态库的使用,如果必须要使用很多动态库,苹果建议将多个动态库合并,理论上支持最多六个动态库合并为一个。

2 APP瘦身。

减少加载启动后不会去使用的类或者方法,包括第三方的类库和自己引用的类库,就算不会被使用,最终也还是会被编译加载到的。
减少不必要的资源文件和废弃文件。

3 减少load()方法里面的操作

+load()方法里的内容可以放到首屏渲染渲染完成后再执行,或使用+initialize()方法替换掉。因为,在一个+load()方法里,进行运行时方法替换操作会带来4毫秒的消耗。不要小看这4毫秒,积少成多,执行+load()方法对启动速度的影响会越来越大。

4 控制C++全局变量的数量。

因为C++的全局变量会在冷启动的过程中进行加载,所以尽量控制这一部分的工作量。

5 二进制重排

上面的方式都是属于老生常谈了,还有一个方式是二进制重排。
这里提供一个了解资料:二进制重排
建议这类知识还是实践出真知,搞个工程自己试试。

main()到didFinishLaunch,做了哪些工作

这一块我比较好奇,又很少有人详细提及,所以做了专门的一篇Runtime源码解读,另外再单独说。

T3过程该如何优化?

除了pre-main的优化工作,在didFinishLaunch被执行到首屏渲染完毕之间,还有几个点可以优化

第三方库的初始化

通常我们会有很多的项目中会用到的第三方库,但是这些第三方库所包含的功能又不是首屏就会用到的,像分享、支付、地图、自定义配置等等,这些可以在首屏渲染完毕之后、具体使用到的页面之前寻找一个合适位置将其初始化加载到内存中。

离屏渲染优化

如果首页包含UITableView,那么一些离屏渲染的问题,也应该纳在考虑范围内,后面离屏渲染会有再详细的解释。

定位功能优化

定位这个操作是一个比较耗时的操作,对页面渲染时间会产生很大的影响。这里现在比较主流的方案是:先发起定位请求,然后使用缓存的上次的定位结果进行预请求或者界面刷新。这样做的好处是,把定位请求的耗时给节省了下来,缺点是如果定位的结果和缓存的不一致,需要重新加载网络请求。

View加载优化

有时候ViewDidLoad里面会进行很多耗时操作,用户还是会感觉到卡顿,关于这点,目前的比较好的方案是首先给用户提供一个空壳,或者一个页面大概内容的图片,然后在ViewDidLoad方法里面进行数据加载和解析渲染等一系列操作。这样一来,用户已经看到界面了,就不会觉得启动慢了,相当于把启动时间转嫁给数据请求时间去背锅了。如果再配合上之前数据的缓存,那么这个启动的效果就会比较可观了。

我曾执笔雕刻时光 奈何良辰难书过往

参考资料:
APP优化总结
iOS优化总结
iOS启动原理
一篇苹果官方讲解的翻译和总结

你可能感兴趣的:(APP性能优化之一 启动优化)