什么时候java比c ++快(或者什么时候JIT更快然后预编译)?

可能重复:
JIT编译器与离线编译器

我听说在某些情况下,由于JIT优化,Java程序或java程序的某些部分能够比C ++(或其他预编译代码)中的“相同”代码执行得更快。 这是因为编译器能够确定某些变量的范围,避免一些条件并在运行时拉出类似的技巧。

你能给出一个(或更好 – 一些)例子吗? 并且可能概述了编译器能够优化字节码超出预编译代码可能性的确切条件?

注意:这个问题不是将Java与C ++进行比较。 它关于JIT编译的可能性。 请不要燃烧。 我也不知道有任何重复。 如果你是的话请指出来。

在实践中,在这些情况下(您个人观察到的所有这些),您可能会发现您天真编写的Java代码优于您天真编写的C ++代码:

  • 大量的内存分配/解除分配。 主要的JVM具有非常高效的内存子系统,垃圾收集比要求显式释放更有效(另外它可以移动内存地址,如果它真的想要的话)。

  • 通过深层次的方法调用进行高效访问。 JVM非常擅长于删除任何不必要的东西,通常比我的大多数C ++编译器(包括gcc和icc)更好。 在某种程度上,这是因为它可以在运行时进行动态分析(即它可以过度优化,只有在检测到问题时才会优化)。

  • 将function封装到小的短期对象中。

在每种情况下,如果你付出努力,C ++可以做得更好(在自由列表和块分配/解除分配的内存之间,C ++几乎可以在每种特定情况下击败JVM内存系统;使用额外的代码,模板和聪明的宏,您可以非常有效地折叠调用堆栈;并且您可以在C ++中使用小于部分初始化的堆栈分配对象,这些对象的性能优于JVM的短期对象模型。 但你可能不想付出努力。

一些例子:

  • JIT编译器可以使用例如最新的SSE扩展来生成非常特定于CPU的机器代码,这些扩展不会在需要运行多种CPU的预编译代码中使用。
  • JIT知道什么时候虚拟方法(Java中的默认方法)不会被覆盖,因此可以内联(尽管这需要能够在加载新类时重新内联它以覆盖该方法;当前的Java JIT编译器实际上这样做)。
  • 与此相关, 转义分析允许几个特定于情境的优化。

维基百科: http : //en.wikipedia.org/wiki/Just-in-time_compilation#Overview

此外,它在某些情况下可以提供比静态编译更好的性能 ,因为许多优化仅在运行时可行

  1. 编译可以针对目标CPU和运行应用程序的操作系统模型进行优化 。 例如,JIT可以在检测到CPU支持时选择SSE2 CPU指令。 要使用静态编译器获得此级别的优化特性,必须为每个预期的平台/体系结构编译二进制文件,或者在单个二进制文件中包含代码的多个部分版本。

  2. 系统能够收集有关程序在其所处环境中实际运行的统计信息,并且可以重新排列和重新编译以获得最佳性能 。 但是,一些静态编译器也可以将配置文件信息作为输入。

  3. 系统可以进行全局代码优化 (例如,库函数的内联),而不会失去动态链接的优点,也不会产生静态编译器和链接器固有的开销。 具体来说,在进行全局内联替换时, 静态编译过程可能需要运行时检查,并确保如果对象的实际类重写内联方法,则可能发生虚拟调用,并且可能需要处理对数组访问的边界条件检查在循环中。 在许多情况下,通过即时编译, 可以将这种处理移出循环,通常可以大大提高速度

  4. 尽管使用静态编译的垃圾收集语言是可行的,但字节码系统可以更容易地重新安排执行的代码以获得更好的缓存利用率

Java的内存管理速度比C ++快得多。 参见Java理论与实践:重新审视城市绩效传说 。