【问题标题】:JIT Optimizations at their finest最佳 JIT 优化
【发布时间】:2012-04-13 05:51:35
【问题描述】:

我已经阅读并听到了很多关于 JIT 编译器如何进行原生代码编译器无法实现的优化以及这些优化可以极大地提升性能的信息。

所以我想知道,有哪些最重要的优化是 .NET Framework 或 JVM 所做的而本地编译器无法做到的?此外,这些如何显着提升性能?

我不知道我这个问题的措辞是否正确,我想我可能在 cmets 中有很多解释要做

【问题讨论】:

  • @TimMedora:该链接似乎在讨论 C# 提前编译器执行的优化,而不是 CLR 即时编译器。

标签: .net performance compiler-construction jvm jit


【解决方案1】:

我可以举一个优化的例子。假设你在某处有一个函数。 (将其视为类 C 的伪代码。)

void function(MyClass x)
{
    x.doSomething();
    for (obj in x.getWidgets())
        obj.doSomethingElse();
}

这是适当的模糊。但是,假设您的整个映像中只有一个具体类继承自MyClassMyConcreteClass。在这种情况下,JIT 可以内联 doSomethinggetWidgets。如果它知道getWidgets返回的类型,那么也许它也可以内联doSomethingElse

这里假设MyClass 不是最终/密封类,提前编译器无法内联其方法(它不知道要内联哪些函数);就编译器所知,MyClass 有一百种不同的实现。

但是,JIT 可以针对图像的当前状态进行优化它可以在每次调用 function 的开头安装检查,以确保 x 是 @987654332 @,然后运行内联版本。如果您使用另一个继承自 MyClass 的具体类动态加载模块,则检查将失败,JIT 会将函数重新编译为泛型。

这些是 JIT 编译器可用但提前编译器不可用的唯一优化类型:利用有关程序动态状态的信息并重新编译相应地编程。

请注意,一些提前编译器能够执行通常归于 JIT 编译器的技巧。例如,过程间优化(或全局优化)和配置文件驱动优化。 GCC 和 Clang 可以同时使用这两种技巧,但大多数人不使用它们,因为它需要额外的(人工)工作才能打开它们。 JIT 编译器可以在不打扰最终用户的情况下启用这些选项。

巨大的性能提升:我没有听说过 JIT 编译器有任何巨大的性能提升。 C 和 C++ 程序在没有 JIT 的情况下仍然很快。许多人仍然更喜欢 Fortran 进行数值工作(有充分的理由)。

脚注:我不确定你的术语。大多数 JIT 不也是本机代码编译器吗?除了 JIT 之外的其他类型的编译器我会称之为“提前”或 AOT,或者可能是“静态”。 (然后“编译”和“解释”之间的界限非常模糊。)

【讨论】:

  • -1 表示“这些是唯一的优化类型......” JIT 编译器使用配置文件引导优化来提高热程序路径上的调用站点性能。 (MSFT CLR 和 Hotspot 都这样做)。那不是程序的“状态”,而是程序的动态。 JIT 编译器可以使用有关它们运行的​​机器的信息来指导优化。 MSFT CLR 执行此操作,Hotspot 执行此操作。这与程序无关。 JIT 编译器还可以使用运行它们的机器的信息状态来指导优化。
  • 我不知道任何当前的虚拟机都会这样做,但肯定有可能。
  • @MichaelGraczyk:我说“这些是唯一一种优化”的原因是因为您提到的优化可以并且实际上是由非 JIT 编译器支持的。 GCC 进行配置驱动的优化。问题只是关于提前编译器无法做到的优化。
  • 我也认为提前编译器为特定机器编译代码是公平的。毕竟,你在野外经常看到它,至少在 Linux 上是这样。
  • 关于这个答案的一些 cmets:1. 如果 C++ 有可用的源代码,它可以内联 doSomething 和 doSomethingElse 和函数 - 2. 在 c++ 中,默认情况下所有类都是最终/密封的 - 你需要明确将函数声明为虚拟函数,与 Java 一样,默认情况下所有方法都是虚拟的。 3.用c++编译器是对的,如果doSomething和friends是虚方法并且没有标记为final(per c++11),它们不会被内联,实际上是为了获取方法的地址,编译器必须在虚拟方法表中查找,(就像没有 jit 的 java 所做的那样)。
【解决方案2】:

Javascript 是一个更好的例子,因为它不像 JVM 或 CLR 那样对编译器友好。

JIT 编译器可以为 Javascript 类生成具体的专门表示,这对于静态编译器来说很难,因为这些类可以在程序执行期间的任何时候修改。您还可以根据实际类型推测性地内联调用的函数(Dietrich Epp 已经在他的回答中解释了这一点)。

http://code.google.com/p/v8/ 的视频很好地解释了这些优化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-12
    • 1970-01-01
    • 1970-01-01
    • 2021-05-06
    • 2015-12-25
    • 1970-01-01
    • 2011-12-26
    • 2011-11-14
    相关资源
    最近更新 更多