美文网首页
iOS启动优化

iOS启动优化

作者: 土豆赶着鸡 | 来源:发表于2019-01-16 16:10 被阅读0次

想做app启动优化,当然是先了解app启动,什么时候开始?什么时候结束?哪里是我们可以去优化的地方?

app启动开始:加载应用的可执行文件Mach-O

app启动结束:调用didFinishLaunchingWithOptions

Mach-O 可执行文件

  • app启动这里我分成两个阶段:pre-main阶段和main()阶段
pre-main阶段

1.加载应用的可执行文件Mach-O

2.加载动态链接库加载器dyld(dynamic loader)

3.dyld递归加载应用所有依赖的dylib (dynamic library动态链接库)

main()阶段

1.dyld调用main()

2.调用UIApplicationMain()

3.调用applicationWillFinishLaunching

4.调用didFinishLaunchingWithOptions

好了,任务分好了,开始干活!!!

注:优化时间=优化前时间-优化后时间

//下面使用模拟器,建议使用真机+release+冷启动,得到数据才最真实

一.pre-main阶段

屏幕快照 2019-01-16 下午1.59.12.png

在 Xcode 中 Edit scheme -> Run -> Arguments 将环境变量DYLD_PRINT_STATISTICS 设为1 ,打钩

屏幕快照 2019-01-16 下午2.05.25.png

根据官方给的四个time,我们可以分为四个步骤

  • 1.load dylibs

这一阶段dyld会分析应用依赖的dylib,找到其mach-o文件,打开和读取这些文件并验证其有效性,递归加载所有依赖库。

一般情况下,iOS应用会加载几百个dylibs,其中大部分是系统库,这部分对dylib的加载做了缓存操作。

所以,依赖的dylib越少越好,我们可以优化的地方:

1.尽可能减少依赖的dylib的数量
2.使用开销较小的dylib

  • 2.rebase/bind

在dylib的加载过程中,系统为了安全考虑,引入了ASLR(Address Space Layout Randomization)技术和代码签名。由于ASLR的存在,镜像(Image,包括可执行文件、dylib和bundle)会在随机的地址上加载,和之前指针指向的地址(preferred_address)会有一个偏差(slide),dyld需要修正这个偏差,来指向正确的地址。

Rebase在前,Bind在后,Rebase做的是将镜像读入内存,修正镜像内部的指针,性能消耗主要在IO。Bind做的是查询符号表,设置指向镜像外部的指针,性能消耗主要在CPU计算。

所以,指针数量越少越好,我们可以做的优化有:

1.减少类Class、方法selector、分类category的数量
2.减少C++虚函数的的数量(创建虚函数表有开销)
3.使用Swift structs(内部做了优化,符号数量更少)

  • 3.Objc setup

大部分ObjC初始化工作已经在Rebase/Bind阶段做完了,这一步dyld会注册所有声明过的ObjC类,将分类插入到类的方法列表里,再检查每个selector的唯一性。

在这一步倒没什么优化可做的,Rebase/Bind阶段优化好了,这一步的耗时也会减少。

  • 4.Initializers

到了这一阶段,dyld开始运行程序的初始化函数,调用每个Objc类和分类的+load方法,调用C/C++ 中的构造器函数(用attribute((constructor))修饰的函数),和创建非基本类型的C++静态全局变量。Initializers阶段执行完后,dyld开始调用main()函数。

在这一步,我们可以做的优化有:

1.少在类的+load方法里做事情,尽量把这些事情推迟到+initiailize

2.减少构造器函数个数,在构造器函数里少做些事情

3.减少C++静态全局变量的个数

二.main()阶段

屏幕快照 2019-01-16 下午3.24.51.png 屏幕快照 2019-01-16 下午3.29.58.png

在mian.m和AppDelegate.m中加上以上代码,可以获得main()之后启动时间

这个阶段牵扯到我们的业务,功能的实现

  • 参考个人项目:在didFinishLaunchingWithOptions方法中
    是否显示引导页、是否需要登录、新版本的检测、注册推送、网络状态的检测、三方库的配置和初始化等
    首页控制器的加载,Tabbar和Nav控制器的加载等

根据个人经验做出一些优化建议:

这一阶段的优化主要是减少didFinishLaunchingWithOptions方法里的时间,所以我们要确认每个任务的时间量(利用CFAbsoluteTimeGetCurrent()方法去计算,计算方法参考上面),然后找出影响大的去做优化(当然时间容许全部优化最好)

1.满足业务前提下,didFinishLaunchingWithOptions在主线程里做的事情越少越好

  • 将三方库和一些功能延迟执行,比如放在首页的viewDidAppear方法中

  • 将三方库和一些功能异步执行,比如异步检测新版本的更新,注册推送

  • 避免多余复杂的计算,比如合适的算法减少运算量和内存消耗

  • 采用性能好的API,轻量级的对象

  • 首页控制器用纯代码方式来构建

相关文章

网友评论

      本文标题:iOS启动优化

      本文链接:https://www.haomeiwen.com/subject/wjnpdqtx.html