App启动分为俩个阶段
pre-main,main()函数之前,系统加载可执⾏⽂件,加载动态链接库dyld,dyld递归加载所有
依赖的动态库,然后dyld调起main()函数。
pre-main分为四个阶段:
i. dylib loading:加载动态库。可以通过减少动态库的数量来优化这⼀部分所消耗的时间。
苹果的建议是⼀个项⽬⾥⾯⾃⼰制作的动态库的数量不超过6个。
ii. ObjC setup:注册Objc类,进⾏selector唯⼀性检测等。可以通过减少Objc类的数量,减
少selector的数量来进⾏优化。
iii. rebase/binding:rebase指针修复,binding符号绑定。这⼀步的优化⼿段和第2步⼀样。
iv. initializer:各种初始化的操作,⽐如执⾏objc的+load函数,C++的构造函数等。不要在
+load函数⾥⾯做⼀些耗时的操作,或者把⼀些操作延时的放在+initialize⾥⾯去执⾏。
main,从main()函数开始到执⾏完appDelegate的didFinishLaunchingWithOptions⽅法展示⾸
⻚数据。
优化⼿段:
i. 少使⽤xib和storyboard。
ii. 删除NSLog打印。
iii. 整理didFinishLaunchingWithOptions⽅法⾥⾯的业务逻辑,可以异步请求的异步请求,可
以延时加载的延时加载。
ASLR
ASLR(address space layout randomization),地址空间布局随机化。是⼀种针对缓冲区溢出的安全
保护技术,通过对堆、栈、共享库映射等线性区布局的随机化,通过增加攻击者预测⽬的地址的难
度,防⽌攻击者直接定位攻击代码位置,达到阻⽌溢出攻击的⽬的的⼀种技术。使得可执⾏⽂件和
动态库在虚拟内存中的地址在每次启动都不固定。
Page Fault
由于虚拟内存的出现,进程不直接访问物理内存,这样安全性更⾼。为了提⾼效率和⽅便管理,对
虚拟内存和物理内存进⾏分⻚(Page)管理。当进程访问⼀个虚拟内存⻚,⽽对应的物理内存却不存在的时候,会触发⼀个缺⻚中断,这个就叫Page Fault。
⼆进制重排
概念 :找到程序在启动时候需要调⽤的符号,然后修改编译参数完成⼆进制⽂件的重新排布。
LinkMap :是iOS编译过程的中间产物,记录了⼆进制⽂件的布局。可以在Xcode的Build Settings
⾥开启Write Link Map File。
order⽂件 :编译器会按照order⽂件的内容,对⼆进制⽂件进⾏排列。可以在Xcode的Build
Settings⾥的Order File处设置。
⼆进制重排能够优化启动时间的原理 :App在执⾏的过程中会存在⼤量的Page Fault,⼀个Page Fault
的耗时很少,但是当⼤量的Page Fault存在时,就会影响到代码的执⾏速度。同理,在App启动的
时候,就可能会出现⼤量的Page Fault。⼆进制重排就是把在启动过程中需要使⽤到的符号,重新
排列在⼀个或者⼏个Page⾥⾯,减少Page Fault的次数,从⽽达到减少启动时间的⽬的。