可能重复:
JIT编译器与离线编译器
我听说在某些情况下,Java程序或者说Java程序的某些部分由于JIT优化可以比C++(或其他预编译代码)执行得更快。这是因为编译器能够确定一些变量的作用域,在运行时避免一些条件和进行类似的技巧。
您能否给出一个(或更好的 - 一些)例子来说明这种情况?并且可能概述编译器能够优化字节码超过预编译代码的确切条件吗?
注意:这个问题不是关于Java和C++的比较。它是关于JIT编译的可能性。请勿争吵。如果有任何重复,请指出。
可能重复:
JIT编译器与离线编译器
我听说在某些情况下,Java程序或者说Java程序的某些部分由于JIT优化可以比C++(或其他预编译代码)执行得更快。这是因为编译器能够确定一些变量的作用域,在运行时避免一些条件和进行类似的技巧。
您能否给出一个(或更好的 - 一些)例子来说明这种情况?并且可能概述编译器能够优化字节码超过预编译代码的确切条件吗?
注意:这个问题不是关于Java和C++的比较。它是关于JIT编译的可能性。请勿争吵。如果有任何重复,请指出。
实际上,在以下情况下(我个人观察到的所有情况),你可能会发现天真编写的Java代码在性能上优于天真编写的C++代码:
大量小内存分配/释放。主要的JVM具有非常高效的内存子系统,垃圾回收可能比需要显式释放更有效(而且如果确实需要,它可以移动内存地址之类的)。
通过深层次的方法调用进行高效访问。JVM非常擅长省略任何不必要的东西,在我的经验中通常比大多数C++编译器(包括gcc和icc)好。部分原因是因为它可以在运行时进行动态分析(即可以过度优化,并且只有在检测到问题时才进行反优化)。
将功能封装到短暂小对象中。
在每种情况下,如果你付出努力,C++可能会更好(在自由列表和块分配/释放内存方面,C++可以在几乎每个具体案例中击败JVM的内存系统;通过额外的代码、模板和聪明的宏,可以非常有效地折叠调用堆栈;在C++中,你可以拥有小的部分初始化的堆栈分配对象,这些对象比JVM的短暂对象模型更有效)。但你可能不想付出这么大的努力。
一些例子:
维基百科:http://en.wikipedia.org/wiki/Just-in-time_compilation#Overview
此外,它在某些情况下可以比静态编译提供更好的性能,因为许多优化只有在运行时才可行:
编译可以被优化到目标CPU和操作系统模型,例如JIT可以在检测到CPU支持SSE2指令时选择使用。要获得这种优化特定性,静态编译器必须为每个预期平台/架构编译二进制文件,或者在单个二进制文件中包含代码部分的多个版本。
系统能够收集程序在其所处环境中实际运行的统计信息,并且可以重新排列和重新编译以获得最佳性能。但是,一些静态编译器也可以将配置文件信息作为输入。
系统可以进行全局代码优化(例如库函数的内联),而不会失去动态链接的优势并且不会产生静态编译器和链接器固有的开销。具体来说,在进行全局内联替换时,静态编译过程可能需要运行时检查,并确保如果对象的实际类覆盖了内联方法,则会发生虚拟调用,并且在循环内可能需要处理数组访问的边界条件检查。使用即时编译,在许多情况下,此处理可以移出循环,通常可以大大提高速度。
虽然静态编译的垃圾收集语言也可以做到这一点,但字节码系统可以更轻松地重新排列执行代码以获得更好的缓存利用率。
Java的内存管理比C++的快得多。请参见Java理论与实践:城市性能传说,重访。
malloc
,例如Wireshark的池分配器就是一个很好的例子。 - Ben Voigt