You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JIT编译器何时将应用程序方法、代码块从CIL转换为原生机器码?

When Does the JIT Compiler Translate CIL to Native Machine Code?

Great question—let’s break down the key scenarios where the JIT (Just-In-Time) compiler kicks in to convert Common Intermediate Language (CIL) to native machine code. I’ve debugged countless performance issues tied to JIT behavior, so this is a topic I’m familiar with.

Primary Trigger: First-Time Execution of a Method/Code Block

This is the most common and core scenario. When the CLR loads your assembly, it doesn’t immediately compile all CIL to native code—this is called lazy compilation. Instead:

  • The first time a method is called (e.g., MyService.ProcessData()), the CLR checks if there’s already native code cached for that method.
  • If no cached native code exists, the JIT compiler is invoked to translate the method’s CIL into optimized native machine code for the target CPU architecture.
  • Once compiled, the native code is stored in memory. All subsequent calls to the same method will reuse this cached code, avoiding re-compilation overhead.

Tiered Compilation: Background Optimization for Hot Methods

Modern .NET runtimes (Core, 5+) enable tiered compilation by default, which splits JIT compilation into two phases:

  • Tier 0: When a method is first called, the JIT quickly generates a basic, unoptimized version of native code. This prioritizes fast startup, so your application becomes responsive sooner.
  • Tier 1: As your application runs, the runtime tracks which methods are called frequently (hot methods). A background JIT thread then re-compiles these hot methods with full optimizations (e.g., inlining, loop unrolling). Once the optimized Tier 1 code is ready, subsequent calls to the method switch to using this improved version.

Explicitly Triggered JIT Compilation

You can force the JIT to compile a method ahead of its first execution using .NET APIs, like:

System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(typeof(MyClass).GetMethod(nameof(MyClass.MyMethod)).MethodHandle);

This is often used during application warm-up phases to eliminate JIT overhead for critical methods before they’re used in production traffic.

Generic Method Instance First Execution

Generic methods are compiled per specific type parameter combination. For example:

  • The first time you call List<int>.Add(42), the JIT compiles the Add method specifically for int.
  • The first time you call List<string>.Add("hello"), the JIT compiles a separate native version of Add for string.
    This is because value types (like int) require different memory handling than reference types, so each generic instance needs its own native code.

Edge Case: Pre-Compiled Assemblies (Non-JIT Scenarios)

Note that if your assembly is pre-compiled using tools like ReadyToRun (R2R) or legacy NGen, most CIL is converted to native code at build time. In these cases, the JIT only kicks in for code that wasn’t pre-compiled (e.g., dynamically generated CIL, some generic instances).

内容的提问来源于stack exchange,提问作者Sybs77

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:36:48