iOS启动优化之二进制重排

随着iOS项目愈来愈大,启动时间也会变得愈来愈慢,咱们如何来对app的启动时间来进行优化,给用户一个更好的体验呢?xcode

应用启动介绍

应用启动分为冷启动和热启动安全

  • 冷启动是指内存中不存在与应用相关的数据,须要从硬盘时将应用的数据载入到内存中;这个过程是由系统决定的,平时咱们把应用杀死,而后立刻启动,此时内存中的应用相关的数据不会立刻被清除,因此这时候的启动不是冷启动;
  • 热启动是指内存中还存留着应用相关的数据,应用运行所须要的数据不须要所有从硬盘中载入内存。

监控启动时间

咱们能够经过设置环境变量来起到监控应用启动时间的目的,有关环境变量的设置,请参考Xcode环境变量markdown

咱们设置环境变量DYLD_PRINT_STATISTICS,运行工程,打印应用启动时的时间消耗状况: 多线程

打印出应用启动时间以下: app

咱们以main函数为分隔点,将应该启动时间优化分为main函数以前和main函数以后,这里所打印的pre-main time就是main函数以前的耗时。函数

  • dylib loading time:动态库的载入耗时,苹果建议项目中自定义的动态库最好不要超过6个动态库,若是超过了6个要考虑动态库合并;
  • rebase/binding time:偏移修正(rebase)和符号绑定(binding)的耗时;偏移修正是一个安全机制--ASLR,原理是生成一个随机值,加到应用内存地址的前面,来起到方法、函数的地址随机的目的,解决安全问题.全部的方法、函数和数据的内存地址都会在原有的真实地址上加上这个随机值,而且每次启动的时候这个随机值是不一样的,这样别人就无法拿到方法、函数或数据的真实地址了;符号绑定是指将方法名与方法的实现,即sel和IMP的绑定。
  • ObjC setup time:Object-C类的注册的耗时;不权威统计,每增长20000个类,这个时间增长800ms;减小类的数量能够减小启动耗时;
  • initializer time:load方法和构造方法的耗时.因此项目中要尽可能减小重写load 方法,将load方法的操做放在initialization中.

以上就是main函数以前的启动耗时说明及相关优化方案;post

对于main函数以后的启动耗时,咱们能够经过代码的方式进行监控,好比,在main函数中记录一个时间,到第一个界面显示的viewDidLoad方法中记录一个时间,两个时间的差值就是main函数以后的启动耗时.因为main函数以后的耗时须要根据不一样的项目来区分,不能一律而论,这里提供几个优化的建议优化

  • 减小数据的加载,最好使用懒加载,如一个第三文库的加载;
  • 将项目中再也不使用的类和方法去掉;
  • 使用多线程技术加载数据,充分利用cpu的资源;
  • 启动时刻的界面,不要使用storyboard或xib,尽可能使用纯代码,由于storyboard或xib有一步代码转换的操做,也是会耗时的。

二进制重排

技术背景

应用程序在运行时,使用的是虚拟内存与物理内存相结合的方法加载数据的;虚拟内存是分页管理的,当使用到某一页虚拟内存的数据时,须要将对应的真实数据加载到物理内存中,将虚拟内存与物理内存以前造成一个映射关系,这个操做称为缺页异常(page fault),这个操做是需耗时的。spa

查看iOS应用的载入数据的顺序,咱们能够经过设置Write Link Map File为yes,来查看应用数据加载的顺序 线程

clean一下工程,而后command+B编绎一下工程,来到Products的xx.app目录下

再来到以下目录下

找到以下文件

打开此文件Demo-LinkMap-normal-x86_64.txt

这里的顺序就是应用数据加载的顺序,这里的顺序是由下以两个因素决定的

按文件顺序从上到下

按文件中的方法的顺序从上到下

验证一下此文件的顺序就是实际的载入顺序,能够经过修改文件或方法的顺序,而后从新编绎后查看link map文件的方法顺序是否改变。

二进制重排方案

因为咱们在应用在启动时可能只须要某些文件中的某些方法,而按照实际的方法载入顺序,在应用启动时会由于page fault的存在,就须要载入大量的用不到的数据,形成了大量的时间消耗,为此咱们只须要在应用启动时只载入启动时须要的方法就能够了,其实的数据能够后续载入;为此咱们能够经过建立一个.order文件来修改方法或函数的加载顺序.

打开hank.order文件,查看如下几个方法的顺序

将此文件配置到对应的xcode工程中

clean后从新编绎,查看Demo-LinkMap-normal-x86_64文件

这样咱们就成功的修改了方法或函数的加载顺序,因此咱们只须要知道应用启动时执行了哪些方法,将他们排序好,放在.order文件中,就能够在应用启动时,只加载了本身须要的数据,减小了page fault的次数,从而减小了启动耗时。

那么如何知道应用启动时执行了哪些方法呢?请看Hook一切的终极武器--Clang插桩

相关文章
相关标签/搜索