iOS 启动优化之设置 Order File - twototwoto/WYW_Blog GitHub Wiki
前言
笔者最近看了一点优化应用启动时间的内容;因为笔者目前没有多少这方面需求,所以目前只做了一部分基本实践;详情如下:
笔者目前了解到的二进制重排的启动优化的初始思路如下:
1.查看应用的启动时间;(看到过部分文章表明400ms左右的启动时间是比较易于接受的)
2.应用启动时,生成Link Map 文件;
3.使用 Profile 工具的 System Trace 工具可以查看具体的 Page Fault 的次数,Page Fault 是影响应用启动的一个原因;
4.我们可以结合着 Link Map 文件中 Symbols 中的内容;(可以发现相应内容和 Build Phases 的 Compile Sources 的路径一致)
5.创建一个 Order File 文件,并把相应的 Link Map 文件中 Symbols 中的内容中的类方法、实例方法等内容复制到 Order File 中。
6.然后重新运行项目,可以查看相应的应用启动时间。
首先我们需要查看项目的启动时间,才能考虑如何优化项目的启动。
一、衡量项目启动时间
在 Xcode 的菜单中选择 Project→Scheme→Edit Scheme,然后找到 Run → Arguments → Environment Variables → +,添加 name 为 DYLD_PRINT_STATISTICS,Value为1的环境变量。
卸载掉应用并且重新启动的启动耗时明细如下:
Total pre-main time: 1.1 seconds (100.0%)
dylib loading time: 838.77 milliseconds (70.8%)
rebase/binding time: 411015771.5 seconds (83502086.3%)
ObjC setup time: 257.88 milliseconds (21.7%)
initializer time: 152.17 milliseconds (12.8%)
slowest intializers :
libSystem.B.dylib : 8.75 milliseconds (0.7%)
libMainThreadChecker.dylib : 56.92 milliseconds (4.8%)
AFNetworking : 31.37 milliseconds (2.6%)
Total pre-main time: 1.0 seconds (100.0%)
dylib loading time: 710.03 milliseconds (68.6%)
rebase/binding time: 411015771.5 seconds (414444153.8%)
ObjC setup time: 254.66 milliseconds (24.6%)
initializer time: 138.55 milliseconds (13.3%)
slowest intializers :
libSystem.B.dylib : 8.12 milliseconds (0.7%)
libMainThreadChecker.dylib : 56.50 milliseconds (5.4%)
AFNetworking : 28.17 milliseconds (2.7%)
使用 Time Profile 的方式启动应用的时候,耗时情况如下:
Total pre-main time: 1.9 seconds (100.0%)
dylib loading time: 1.1 seconds (59.3%)
rebase/binding time: 419.98 milliseconds (21.6%)
ObjC setup time: 225.18 milliseconds (11.5%)
initializer time: 144.94 milliseconds (7.4%)
slowest intializers :
libSystem.B.dylib : 8.99 milliseconds (0.4%)
libMainThreadChecker.dylib : 59.22 milliseconds (3.0%)
二、查看Page Fault
Product → Profile (或使用快捷键 command + i ) 启动 Instruments。
选择 System Trace
点击右上角的 圆形红色录制 按钮以启动应用并开始检测。
点击左上角按钮开始录制
点击录制后的效果如下图
点击左上角按钮停止录制
点击停止录制后的效果如下图
停止后的效果如下图
查看Main Thread 的 Page Fault 的次数。
注意把应用 Terminate 掉,否则可能出现下图没有 Page Fault 的情况。如果还没有 Page Fault,可以把应用卸载掉,重新安装。
下图笔者的这个数据还是不大准确,可能是之前多次启动过应用,然后有缓存的原因。
笔者把应用卸载掉,重新安装应用又做了尝试。
最终 Page Fault 效果图如下:
可以发现 Page Fault 的次数还是比较多的,有 2042 次,耗时为 654.66ms。
三、查看当前链接过程
查看链接过程的方式为 选择相应 Target → Build Settings → 搜索 Write Link Map File 把 No 改为 YES。
查看生成的 Link Map txt 文件的方式如下图所示
打开Link Map txt 文件,可以发现 .o 文件的加载顺序和我们的 Build Phases → Compile Sources 中的文件编译顺序一致。 这个Link Map txt 文件貌似需要应用运行的时候会生成,而且如果生成后,把该文件删除掉的话,再次运行项目也并不会生成相应文件,而且把应用卸载掉,也没有重新生成相应 txt 文件。笔者为了查看Link Map txt 文件详情,自己在其他文件目录创建了空白 txt 文件,然后设置了 Link Map 相应路径文件,之后再运行应用,可以发现我们设置的 Link Map 的 txt 文件已经填充了相应内容。
四、设置 Order File
设置 Order File 的方式为 选择相应 Target → Build Settings → 搜索 Order File。效果如下图所示。
设置 Order File 的方式为 选择相应 Target → Build Settings → 搜索 Order File
然后根据 Link Map txt 文件中的 Symbols 之后的内容的类方法和实例方法复制到 Order File 中。
这种方式就能避免掉 Page Fault。
设置Order File 后未生效的情况
Total pre-main time: 1.6 seconds (100.0%)
dylib loading time: 468.09 milliseconds (28.3%)
rebase/binding time: 856.67 milliseconds (51.8%)
ObjC setup time: 189.32 milliseconds (11.4%)
initializer time: 139.35 milliseconds (8.4%)
slowest intializers :
libSystem.B.dylib : 9.04 milliseconds (0.5%)
libMainThreadChecker.dylib : 69.03 milliseconds (4.1%)
设置Order File 后部分生效后的情况,总体启动时间是减少了,不过看起来 rebase/binding time 输出有些异常。
Total pre-main time: 218.11 milliseconds (100.0%)
dylib loading time: 140.00 milliseconds (64.1%)
rebase/binding time: 411015771.6 seconds (197728971.8%)
ObjC setup time: 15.13 milliseconds (6.9%)
initializer time: 82.89 milliseconds (38.0%)
slowest intializers :
libSystem.B.dylib : 6.88 milliseconds (3.1%)
libBacktraceRecording.dylib : 8.04 milliseconds (3.6%)
libMainThreadChecker.dylib : 34.60 milliseconds (15.8%)
AFNetworking : 26.65 milliseconds (12.2%)
Total pre-main time: 245.15 milliseconds (100.0%)
dylib loading time: 138.75 milliseconds (56.6%)
rebase/binding time: 411015771.6 seconds (421708252.1%)
ObjC setup time: 21.73 milliseconds (8.8%)
initializer time: 106.66 milliseconds (43.5%)
slowest intializers :
libSystem.B.dylib : 7.70 milliseconds (3.1%)
libBacktraceRecording.dylib : 7.89 milliseconds (3.2%)
libMainThreadChecker.dylib : 37.77 milliseconds (15.4%)
AFNetworking : 44.46 milliseconds (18.1%)