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

点击右上角的 圆形红色录制 按钮以启动应用并开始检测。

System Trace.png

点击左上角按钮开始录制

image.png

点击录制后的效果如下图

image.png

点击左上角按钮停止录制

image.png

点击停止录制后的效果如下图

image.png

停止后的效果如下图

查看Main Thread 的 Page Fault 的次数。

image.png

注意把应用 Terminate 掉,否则可能出现下图没有 Page Fault 的情况。如果还没有 Page Fault,可以把应用卸载掉,重新安装。

image.png

下图笔者的这个数据还是不大准确,可能是之前多次启动过应用,然后有缓存的原因。

image.png

笔者把应用卸载掉,重新安装应用又做了尝试。

最终 Page Fault 效果图如下:

image.png

可以发现 Page Fault 的次数还是比较多的,有 2042 次,耗时为 654.66ms。

三、查看当前链接过程

查看链接过程的方式为 选择相应 Target → Build Settings → 搜索 Write Link Map File 把 No 改为 YES。

image.png

查看生成的 Link Map txt 文件的方式如下图所示

image.png

打开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。效果如下图所示。 image.png

设置 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%)

五、参考学习网址

其他启动相关文章