代码之家  ›  专栏  ›  技术社区  ›  jsight TaherT

NET CLR JIT是否每次都编译每个方法?

  •  26
  • jsight TaherT  · 技术社区  · 15 年前

    我知道Java的 HotSpot CLR 基于类似启发式的工作?

    4 回复  |  直到 8 年前
        1
  •  44
  •   Jon Skeet    9 年前

    注意:此答案在“每次运行”上下文中。每次运行程序时,代码通常都是jit的。使用 ngen .NET Native 也改变了这个故事。。。

    确切地 每次运行一次。它从不解释,也从不根据实际使用情况以比以前更重的优化重新编译。

    当然,这可能会改变,但从v1开始就是这样,我不希望很快改变。

    它的优点是它使得JIT变得更简单——不必考虑已经运行的“旧”代码,基于不再有效的前提下取消优化。

    NET的优势之一是,大多数CLR语言默认情况下使方法非虚拟,这意味着可以进行更多的内联。HotSpot可以内联一个方法,直到它第一次被重写,在这一点上它取消了优化(或者在某些情况下做了一些聪明的事情,根据实际类型有条件地仍然使用内联代码)。由于需要担心的虚拟方法较少,.NET在很大程度上可以忽略无法内联任何虚拟内容的痛苦。

    显然,微框架根本没有JIT,而是解释代码。这对于非常受限的设备是有意义的。(我不能说我对微观框架了解很多。)

        2
  •  14
  •   Community Bayu Bramantya    4 年前

    NET运行时总是在执行之前编译代码JIT。因此,它从未被解释过。

    你可以在书中找到一些更有趣的读物 CLR Design Choices 具有 Anders Hejlsberg . 特别是:

    我读到微软决定IL将永远被编译,而不是被解释。指令中的编码类型信息如何帮助口译员更高效地运行?

    Anders Hejlsberg:如果解释器可以盲目地执行指令所说的内容,而不需要跟踪堆栈顶部的内容,那么它可以运行得更快。例如,当它看到一个iadd时,解释器不必首先找出它是哪种类型的加法,它知道它是一个整数加法。假设有人已经验证了堆栈看起来是正确的,那么在那里缩短一些时间是安全的,对于解释器来说,您关心的是这一点。不过,在我们的例子中,我们从未打算使用CLR来针对已解释的场景。我们打算始终使用JIT[即时编译],并且出于JIT的目的,我们仍然需要跟踪类型信息。因为我们已经有了类型信息,它实际上并没有给我们买任何东西来把它放在说明中。

    比尔·维纳斯:许多现代JVM(Java虚拟机)都进行自适应优化,从解释字节码开始。他们在应用程序运行时对其进行分析,找出80%到90%执行时间的10%到20%的代码,然后将其编译为本机代码。不过,他们不一定要及时编译这些字节码。方法的字节码仍然可以由解释器执行,因为它们被编译为本机代码并在后台进行优化。当本机代码就绪时,它可以替换字节码。通过不针对解释的场景,您是否完全排除了在CLR中执行的方法?

    安德斯·海尔斯伯格:不,我们还没有完全排除这种可能性。我们仍然可以解释。我们只是不适合口译。我们不适合编写性能最高的解释器,它只会进行解释。我想再也没有人这样做了。对于10年前的机顶盒来说,这可能很有趣。但是它不再有趣了。JIT技术已经发展到可以有多种可能的JIT策略的地步。你甚至可以想象使用一个快速的JIT,它只是快速的撕裂,然后当我们发现我们一直在执行一个特定的方法时,使用另一个JIT,它花费更多的时间,并且在优化方面做得更好。在JIT方面,你还可以做很多事情。

        3
  •  3
  •   Peter Mortensen TravisEz13    8 年前

    在未来,对于内存不足的设备,看到一些基于跟踪的JIT将是一件好事。它将主要解释、发现热点,并将其转换为汇编程序并缓存。我认为这就是谷歌用Android JIT和 Microsoft Research

    SPUR: A Trace-Based JIT Compiler for CIL .. 也许其中的一部分会进入下一阶段 CLR 有一天?

        4
  •  0
  •   Andrew Hare    15 年前

    我不这么认为,我也不认为应该这样。

    JIT怎么知道一个特定方法会被调用多少次?解释的频率不会影响决策吗?

    我还想问JIT编译器在不解释函数本身的情况下,如何分析函数以确定解释是否是最好的。考虑到这一事实(该方法至少有一个过程已经发生),简单地编译每个方法不是更好,以减少试图确定哪些方法首先被编译的开销吗?