Tiered Compilation 是 .NET Core 3.0+ 的分层 JIT 策略,先以 Tier 0 快速生成低优化代码启动,再按需升级为启用内联、边界检查消除等深度优化的 Tier 1 代码,默认开启且关闭可能降低长周期服务吞吐量。
什么是 Tiered Compilation(分层编译)
Tiered Compilation 是 .NET Core 3.0+ 引入的 JIT 编译策略,它让同一段 IL 代码在运行时可被多次编译——先用快但质量低的方式(Tier 0),再按需升级为慢但优化强的方式(Tier 1)。这不是“一次编译、永久运行”,而是“边跑边调优”。
默认开启(DOTNET_TieredCompilation=1),关掉反而可能降低吞吐量,尤其对长周期服务。
- Tier 0:JIT 极速生成代码,几乎不内联、不循环展开、不进行逃逸分析,只为快速启动
- Tier 1:JIT 重新编译热点方法,启用完整优化(如内联
MethodImplOptions.AggressiveInlining方法、向量化、类型特化) - 触发条件由运行时统计决定:方法被调用次数 + 循环执行次数达到阈值(非固定值,受 GC 压力、CPU 负载等动态调整)
怎么观察 Tiered Compilation 是否生效
最直接方式是看 JIT 日志或用 dotnet-trace 捕获 Jit/JitStart 和 Jit/MethodCompiled 事件,但日常调试更推荐:
- 设置环境变量:
DOTNET_JitDisasm=YourMethodName(只对指定方法输出汇编) - 搭配
DOTNET_JitDisasmAsm=true可看到 tier 信息,例如输出里出现[Tier-0] YourMethodName和后续的[Tier-1] YourMethodName - 用
PerfView录制并查看JIT/MethodJITTED事件,字段Tier列会显示 0 或 1
注意:DOTNET_JitDisasm 仅影响当前进程,且只对 JIT 编译的方法生效(AOT 编译或已 Tier-1 的方法不会重复打印)。
JIT 在 Tier 1 里实际做了哪些关键优化
Tier 0 和 Tier 1 生成的机器码差异远不止“多几个寄存器分配”。真正影响性能的是这几类决策是否启用: