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

时间:2010-12-23 07:48:13

标签: java performance optimization compiler-construction jit

  

可能重复:
  JIT compiler vs offline compilers

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

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

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

4 个答案:

答案 0 :(得分:38)

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

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

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

  • 将功能封装到小型短期对象中。

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

答案 1 :(得分:7)

一些例子:

  • JIT编译器可以使用例如生成特定于CPU的机器代码。最新的SSE扩展,不需要在需要运行各种CPU的预编译代码中使用。
  • JIT知道虚拟方法(Java中的默认方法)何时不被任何地方覆盖,因此可以内联(尽管这需要能够在加载新类时取消内联,但会覆盖该方法;当前Java JIT编译器实际上是这样做的。)
  • 与此相关,escape analysis允许特定情况的几种优化。

答案 2 :(得分:6)

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

  

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

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

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

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

  6.   
  7. 尽管使用静态编译的垃圾收集语言可以实现这一点,但字节码系统可以更轻松地重新排列执行的代码以提高缓存利用率

  8.   

答案 3 :(得分:0)

Java内存管理比C ++快得多。设置Java theory and practice: Urban performance legends, revisited