ReadyToRun 编译怎么开
ReadyToRun(R2R)是 .NET 5+ 中对 IL 程序集做的提前编译优化,生成平台相关的机器码镜像,运行时可跳过 JIT 编译阶段。它不是独立构建模式,而是
dotnet publish的一个选项: 必须用
Release配置,Debug 下默认禁用 需指定
--runtime(如
win-x64、
linux-arm64),R2R 镜像是平台绑定的 启用方式:加
--no-self-contained false(默认)或
--self-contained true,再加
--crossgen2参数(.NET 6+ 默认启用
crossgen2) 显式开启 R2R:在
.csproj中添加
<publishreadytorun>true</publishreadytorun>
示例命令:
dotnet publish -c Release -r win-x64 --self-contained true -p:PublishReadyToRun=true
生成的输出目录里,
.dll文件会被
crossgen2处理成含本地代码的“R2R 镜像”,文件大小明显增大,且
dotnet --list-runtimes不影响其运行(它仍依赖 .NET 运行时)。
R2R 和 Native AOT 的根本区别
R2R 是“带本地代码的托管程序”,Native AOT 是“彻底脱离运行时的原生二进制”。二者目标相似(启动快、内存省),但技术路径和约束完全不同:
ReadyToRun仍依赖完整 .NET 运行时(
libcoreclr.so或
coreclr.dll),只是把部分方法提前编译了;
nativeaot输出的是纯原生可执行文件,不带任何托管运行时组件 R2R 支持反射、动态加载(
Assembly.Load)、
eval类 API(如
Expression.Compile);Native AOT 在编译期就要确定所有可达代码,反射需用
[DynamicDependency]或
TrimmerRootDescriptor显式声明 R2R 编译快、兼容性高,几乎不用改代码;Native AOT 构建慢、限制多,常见报错如
ILLink failed: 'System.Reflection.MissingMetadataException',意味着某处反射没被正确标注 R2R 输出仍是
.dll(含嵌入本地代码),靠运行时加载;Native AOT 输出是
.exe(Windows)或无扩展名可执行文件(Linux/macOS)
什么时候该选 R2R 而不是 Native AOT
如果你的应用需要以下任一能力,R2R 是更现实的选择:
使用第三方 NuGet 包(尤其是含大量反射或运行时代码生成的库,如Newtonsoft.Json、
EntityFrameworkCore、
AutoMapper) 依赖插件机制(
AssemblyLoadContext.LoadFromAssemblyPath) 调用
System.Text.Json.SourceGeneration以外的源生成器(R2R 兼容所有源生成器) 部署环境无法预装 .NET 运行时,但允许你打包自包含运行时(R2R +
--self-contained true即可)
Native AOT 只适合“可控边界清晰”的场景:CLI 工具、云函数、嵌入式服务端逻辑,且你愿意为每个反射调用加
[UnconditionalSuppressMessage]或重写逻辑。
R2R 常见失效原因和验证方法
R2R 不是开了就一定生效——编译成功不代表所有类型都被处理。容易被忽略的点:
未设置<publishtrimmed>false</publishtrimmed>且同时启用了 trimming(.NET 6+ 发布时默认 trim),会导致 R2R 被静默禁用(日志中出现
Skipping ReadyToRun compilation because trimming is enabled) 引用了
Microsoft.NET.Sdk.BlazorWebAssembly等 SDK,会强制关闭 R2R(Blazor WebAssembly 不支持) 验证是否生效:用
corflags <your.dll></your.dll>(Windows)或
readelf -S <your.dll> | grep r2r</your.dll>(Linux),看到
R2R或
.r2rdata段即表示已编译;也可用
dotnet trace观察启动时是否有
JITCompilationStarted事件大幅减少
R2R 的“镜像”本质是优化而非替代,它和 JIT 共存:未覆盖的方法、泛型实例化、动态生成代码仍走 JIT。别把它当成 Native AOT 的简易平替——该踩的兼容性坑,一个都不会少。
