8

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

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

我不知道我是否正确地表达了这个问题,我想我可能在评论中有很多解释要做

4

2 回答 2

4

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

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

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

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

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

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

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

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

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

于 2012-04-13T08:22:11.740 回答
1

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

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

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

于 2012-04-13T10:27:28.617 回答