扫一扫关注公众号,获得更多iOS相关内容
这篇文章会给大家介绍一下关于启动优化,我们可以从哪些方面入手,而不会讲具体的实现,具体的实现会在后面其它专题的文章中陆续给大家引出来。
这篇文章所提的启动都是冷启动。
为什么要进行启动优化
在进行启动优化之前,我们首先要知道为什么要进行启动优化,相信看了下面这组数据,你就会意识到启动优化的重要性:
- iOS应用启动时间一旦超过20s,系统会认为发生了死循环并杀掉App进程。
- 互联网领域八秒定律是指用户访问一个网站时,如果等待网页打开的时间超过8秒,会有超过70%的用户放弃等待。
- 如果应用启动时长超过3秒,会有70%的用户直接卸载应用。
启动时间的计算方式
iOS冷启动过程为:从用户点击App图标开始到appDelegate didFinishLaunching方法执行完成为止。这个过程主要分为两个阶段:
- main()函数之前:即操作系统加载App可执行文件到内存,然后执行一系列的加载、链接等工作,最后执行至App的main()函数。
- main()函数之后:即从main()开始,到appDelegate的didFinishLaunchingWithOptions方法执行完毕。
启动时间(T)= main()函数执行之前的时间(T1)+ main()函数执行之后的时间(T2).
如何测量启动时间
测量main()函数之前的时间
dyld里有内置的测量系统,可以通过设置环境变量访问:
测量main()函数之后的时间
这段时间我们可以通过插入代码来测量。
- 先在main()函数里用变量StartTime记录当前时间:
CFAbsoluteTime StartTime;
int main(int argc, char * argv[]) {
StartTime = CFAbsoluteTimeGetCurrent();
...
}
- 在AppDelegate.m文件中用extern声明全局变量StartTime
extern CFAbsoluteTime StartTime;
- 在didFinishLaunchingWithOptions里,获取一下当前时间,与StartTime的差值即是main()函数之后的运行时间。
double launchTime = (CFAbsoluteTimeGetCurrent() - StartTime);
开始启动优化
启动速度要多快
苹果的经验法则告诉我们:400ms是一个不错的启动时间。 **注意:**在测量启动时间时,需要在最慢的支持设备上进行测试。
main()函数之前
先回顾下Dyld的加载步骤:
接下来我们从这几个步骤来分析下有哪些可以进行启动优化的点Load dylibs
平均每个应用会包含100到400个dylib,但是系统的dylibs非常快。 加载内嵌的dylib非常昂贵。
优化方案:依赖的dylib越少越好。
- 尽量不使用内嵌的dylib。
- 合并已有的dylib。
- 使用dlopen()函数懒加载dylib,不建议用。因为,dlopen()会带来细微的性能和正确性的问题,实际在之后会带来更多的工作量。
Rebase & Bind
Rebase由于有许多I/O操作,会慢一些,而Bind在计算上会昂贵一些。其时间都消耗在修复__DATA段里的指针上。
优化方案:减少修复指针的数量
- 减少ObjC类(class)、方法(selector)、分类(category)的数量。
- 减少C++虚函数的的数量。
- 使用Swift structs,Swift语言内部做了优化,符号量更少且更内联。
ObjC
大部分ObjC初始化工作已经在Rebase & Bind阶段完成了,这一步dyld会注册所有声明过的ObjC类,将分类插入到类的方法列表中,再检查每个selector的唯一性。
优化方案:同Rebase & Bind
initializers
这个阶段,dyld开始运行程序的初始化函数,调用每个Objc类和分类的+load方法,调用C/C++ 中的构造器函数(用attribute((constructor))修饰的函数),和创建非基本类型的C++静态全局变量。
优化方案:
- 少使用+load方法
- 尽量把这些事情推迟到+initiailize
- 将+load方法的加载与执行分离,加载放到main之前执行大概耗时5毫秒,执行放到main之后的一个合适的时机。后面,我会专门写一篇文章来介绍这个方案。
- 减少构造器函数个数,在构造器函数里少做些事情。
- 减少C++静态全局变量的个数。
main()函数之后
这一阶段要根据具体的业务进行优化,这里不做过多阐述,后面的文章中也会有相关内容,记住指导原则:在满足业务需要的前提下,didFinishLaunchingWithOptions在主线程里做的事情越少越好。