启动优化(一)-理论篇
启动优化(二)-二进制重排篇
启动优化(三)-编译期插桩篇
启动优化(四)-生成 Order File
二进制重排的效果
把所有启动需要使用到的符号全部放在前面的页码,从而减少Page Fault
的次数,最后达到减少启动时消耗的时间。
能减少Page Fault
次数的原因:
把启动阶段所需要的符号都挤放在最前面的同一个/几个page
,这样在启动时候所需要加载的page
的个数减少了,从而达到减少Page Fault
次数。
重排目的
二进制重排就是为了减少启动时的缺页异常Page Fault
从而减少启动时间(相关概念请看理论篇)
查看 Page Fault
打开Instruments: 快捷键 command+i
当代码多起来的话,Page Fault
的数量和加载耗时都会随着代码增加而增加。并且双击还能看到Page Fault堆栈
二进制重排
可以很好优化这个问题,其中心思想是重新排列 方法符号的顺序, 使启动的相关方法排在最前面从而减少启动Page Fault的数量。
我们先来看看原来的符号顺序,这需要用到 链接映射文件 Link Map File
。
Link Map File 里可以看到方法符号的排序。知道了原来的符号排序,开发者怎么去设置自己想要的顺序呢?
order_file
Xcode提供了排列符号的设置给开发者,设置 order_file
即可。苹果也一直身体力行,objc
源码就采用了二进制重排优化。
把 objc源码 下载好,把源码根目录的libobjc.order
复制到根目录改名为link.order
文件,这里面就是方法符号的排序
Target
-> Build Setting
-> Linking
-> Order File
设置 order file 的路径: $(SRCROOT)/link.order
编写order_file
不知道怎么编写order?我们可以参照 objc源码 里的order编写
Link Map File
现实原来是先加载-[AppDelegate application:didFinishLaunchingWithOptions:]
后加载 -[ViewController viewDidLoad]
编写一下link.order
然后command+shift+K,再command+B重新编译一下,再查看一下 Link Map File
,顺序已经换过来了
手动写入容易出错,比如手填两个不存在的方法,也一样编译通过,并且Link Map File并不会添加这两个不存在错误的方法
自动生成order_file
全手写一定是不可取的,想实现自动化就要解决下列问题:
1.保证不遗漏方法
2.保证方法符号正确
3.保证方法符号顺序正确
解决方案可见抖音团队分享
使用的是 静态扫描+运行时trace的方案, 能够覆盖到80%~90%的符号。但是上述的方法也存在性能瓶颈
:
1.initialize hook不到
2.部分block hook不到
3.C++通过寄存器的间接函数调用静态扫描不出来
解决以上问题:编译期插桩