Xamarin.Mac 在编译之前

概述

提前 (AOT) 编译是一种强大的优化技术,可用于提高启动性能。 但是,它还以深刻的方式影响生成时间、应用程序大小和程序执行。 为了了解它施加的权衡,我们将深入探讨应用程序的编译和执行。

用托管语言(如 C# 和 F#)编写的代码编译为名为 IL 的中间表示形式。 此 IL 存储在库和程序程序集中,在处理器体系结构之间相对紧凑且可移植。 但是,IL 只是一组中间指令,在某些时候,IL 需要转换为特定于处理器的计算机代码。

有两点可以完成此处理:

  • 恰时 (JIT) - 在应用程序的启动和执行过程中,IL 在内存中编译为计算机代码。
  • 提前 (AOT) - 在生成期间,IL 将编译并写出到本机库,并存储在应用程序捆绑包中。

每个选项都有一些好处和利弊:

  • JIT
    • 启动时间 – 必须在启动时完成 JIT 编译。 对于大多数应用程序,此顺序为 100 毫秒,但对于大型应用程序,这个时间可能要大得多。
    • 执行 – 由于 JIT 代码可以针对正在使用的特定处理器进行优化,因此可以生成稍微更好的代码。 在大多数应用程序中,这最多要快一些百分点。
  • AOT
    • 启动时间 – 加载预编译的动态库明显快于 JIT 程序集。
    • 磁盘空间 – 这些动态库可能需要大量的磁盘空间。 根据哪些程序集是 AOTed,它可以将应用程序的代码部分的大小加倍或更多。
    • 生成时间 – AOT 编译明显较慢,JIT 会降低使用它的生成速度。 根据编译的程序集的大小和数量,此速度可能从秒到一分钟或更慢。
    • 模糊处理 – 由于 IL 比机器代码更容易反向工程,因此不一定需要它来帮助模糊化敏感代码。 这需要下面所述的“混合”选项。

启用 AOT

将来的更新中,AOT 选项将添加到 Mac 生成窗格中。 在此之前,启用 AOT 需要通过 Mac Build 中的“其他 mmp 参数”字段传递命令行参数。 选项如下:

--aot[=VALUE]          Specify assemblies that should be AOT compiled
                          - none - No AOT (default)
                          - all - Every assembly in MonoBundle
                          - core - Xamarin.Mac, System, mscorlib
                          - sdk - Xamarin.Mac.dll and BCL assemblies
                          - |hybrid after option enables hybrid AOT which
                          allows IL stripping but is slower (only valid
                          for 'all')
                          - Individual files can be included for AOT via +
                          FileName.dll and excluded via -FileName.dll

                          Examples:
                            --aot:all,-MyAssembly.dll
                            --aot:core,+MyOtherAssembly.dll,-mscorlib.dll

混合 AOT

在执行 macOS 应用程序期间,运行时默认使用从 AOT 编译生成的本机库加载的计算机代码。 但是,有些代码区域(如 trampolines),其中 JIT 编译可以产生明显更优化的结果。 这要求托管程序集 IL 可用。 在 iOS 上,应用程序不受 JIT 编译的任何使用的限制;这些代码部分也编译了 AOT。

混合选项指示编译器同时编译这些部分(如 iOS),但也假定 IL 在运行时不可用。 然后,可以在生成后去除此 IL。 如上所述,运行时将被迫在某些地方使用不太优化的例程。

其他注意事项

AOT 缩放的负面影响,以及处理程序集的大小和数量。 例如,完整目标框架包含的基类库 (BCL) 比新式要大得多,因此 AOT 需要更长的时间并生成更大的捆绑包。 这因完全目标框架与链接不兼容而复合,该链接去除了未使用的代码。 请考虑将应用程序移动到新式,并启用链接以获得最佳结果。

AOT 的另一个好处是改进了与本机调试和分析工具链的交互。 由于大部分代码库将提前编译,因此它将具有更易于在本机故障报告、分析和调试中读取的函数名称和符号。 JIT 生成的函数没有这些名称,通常显示为难以解析的未命名十六进制偏移量。