C#JIT编译和.NET

Ste*_*eve 77 c# jit

我对JIT编译器的工作原理有点困惑.我知道C#编译成IL.第一次运行它是JIT'd.这是否涉及将其翻译成本机代码?.NET运行时(作为虚拟机吗?)是否与JIT代码交互?我知道这很天真,但我真的很困惑.我的印象一直是.NET运行时没有解释程序集,但我不了解交互的细节.

dth*_*rpe 75

是的,JIT的IL代码涉及将IL转换为本机机器指令.

是的,.NET运行时与JIT的本机机器代码交互,因为运行时拥有本机机器代码占用的内存块,运行时调用本机机器代码等.

你是正确的,.NET运行时不解释程序集中的IL代码.

当执行到达一个尚未被JIT编译成本机机器代码的函数或代码块(如if块的else子句)时,会调用JIT'r将IL块编译为本机机器码.完成后,程序执行进入刚刚发出的机器代码以执行它的程序逻辑.如果在执行本机机器代码执行时到达对尚未编译为机器代码的函数的函数调用,则调用JIT'r以"及时" 编译函数.等等.

JIT'r不一定将函数体的所有逻辑编译成机器代码.如果函数具有if语句,则在执行实际通过该块之前,if或else子句的语句块可能不会被JIT编译.未执行的代码路径在执行之前保持IL格式.

已编译的本机机器代码保存在内存中,以便下次执行该代码段时可以再次使用它.第二次调用函数时,它将比第一次调用它时运行得更快,因为第二次不需要JIT步骤.

在桌面.NET中,本机机器代码在应用程序域的生命周期内保存在内存中.在.NET CF中,如果应用程序内存不足,则可能会丢弃本机机器代码.在下次执行该代码时,将从原始IL代码再次编译JIT.

  • 至于*为什么*这样做,主要是因为非jit编译器不能假设某些优化在任何给定的目标平台上都可用.唯一的选择是编译到最小的公分母,或者更常见的是编译多个版本,每个版本都针对它自己的平台.JIT消除了这种缺点,因为最终转换为机器代码是在目标机器上完成的,编译器知道哪些优化是可用的. (17认同)
  • 小修辞 - 'JIT'r不一定编译函数体的所有逻辑' - 在理论实现中可能就是这种情况,但在.NET运行时的现有实现中,JIT编译器将编译整个方法一下子. (13认同)
  • Chris,即使 JIT 知道可以进行哪些优化,它也没有时间应用任何重要的优化。可能NGEN更强大。 (2认同)
  • @Grigory是的,NGEN拥有JIT编译器没有的时间,但是JIT可以做出很多代码生成决定来提高编译代码的性能,而这些代码不需要花费很多时间来解决.例如,JIT编译器可以选择指令集以最好地匹配在运行时找到的可用硬件,而无需为JIT编译步骤增加大量时间.我认为.NET JITter不会以任何重要的方式实现这一点,但它是可能的. (2认同)

Meh*_*dad 21

代码被"编译"为Microsoft中间语言,类似于汇编格式.

双击可执行文件时,Windows会加载mscoree.dll,然后设置CLR环境并启动程序代码.JIT编译器开始读取程序中的MSIL代码,并将代码动态编译为x86指令,CPU可以执行这些指令.