.NET的NativeAOT编译指南

什么是AOT有何优点

JIT(即时编译): 是一种在程序运行之前将源代码或中间代码编译成目标平台的机器代码或可执行代码的编译技术。
AOT(提前编译): 是一种编译技术,它在程序运行之前将源代码或中间代码(如字节码)转换为目标平台的机器代码。

AOT相对JIT优点:

  • 更快的启动时间:译。
  • 更小的内存占用:可以在不需要安装.NET运行时的环境中运行。
  • 不依赖.NET环境: 生成一个包含环境的单应用程序, 且都已编译成本机代码, 可以在无.NET环境中运行

AOT配置

// XXX.csproj文件中加入如下配置
<PropertyGroup>
    <PublishAot>true</PublishAot> <!-- AOT发布 -->
</PropertyGroup>

// AOT 兼容性分析仪, 添加如下代码后, 默认启用了以下参数
// IsTrimmable(是否可修剪) = true
// EnableTrimAnalyzer(开启修剪分析) = true
// EnableSingleFileAnalyzer(开启单文件分析) = true
// EnableAotAnalyzer(开启单文件分析) = true
// 这些分析器有助于确保库与本机AOT兼容, 也就是说分析通过后可以确保AOT编译通过
<PropertyGroup>
    <IsAotCompatible>true</IsAotCompatible> <!--指示[库]是否与本机AOT兼容-->
</PropertyGroup>

// 发布到指定平台
dotnet publish -r win-x64 -c Release

// 将调试符号从Linux上生成的可执行文件剥离到单独的文件中。.NET8之前默认false, .NET8以上默认true
<StripSymbols>true</StripSymbols>

// 优化部署: 针对大小或速度进行优化
<OptimizationPreference>Size</OptimizationPreference> <!--优先考虑可执行文件的大小-->
<OptimizationPreference>Speed</OptimizationPreference> <!--优先考虑代码执行速度-->
// 程序裁剪配置, [很多参数见"扩展阅读"]
<PublishTrimmed>true</PublishTrimmed> <!--启用剪裁-->
<TrimMode>full</TrimMode> <!--剪裁粒度:full(默认)全部,partial仅剪裁已选择剪裁的程序集-->
// 如果选择partial, 那么可以通过如下配置需要裁切的程序集
<ItemGroup>
  <TrimmableAssembly Include="MyAssembly" />
</ItemGroup>

本机AOT部署的限制

  • 无动态加载,例如 Assembly.LoadFile
  • 无生成运行时代码,例如 System.Reflection.Emit
  • 需要修剪代码,不兼容修剪的组件不支持:1)基于反射的序列化程序;2)动态加载程序集;3)通过JIT进行运行时代码生成Emit;4)
    内置COM封送
  • System.Linq.Expressions 始终使用其解释形式,这比运行时生成的编译代码慢。

RequiresDynamicCodeAttribute

它是一个Attribute,表示成员已被批注为与 AOT 不兼容。此批注意味着该成员可能使用反射或其他机制在运行时创建新的本机代码。当代码从根本上与 AOT 不兼容时,或者本机依赖项过于复杂而无法在生成时静态预测时,将使用此属性。

[RequiresDynamicCode("Use 'MethodFriendlyToAot' instead")]
void MethodWithReflectionEmit() { ... }

改造本程序的AOT支持

第三方库AOT支持

后续补充

扩展阅读

.NET NativeAOT 指南
dotnet7 aot编译实战
如何使库与本机 AOT 兼容(一)
如何使库与本机 AOT 兼容(二)
官方AOT: 剪裁选项

此处评论已关闭