Java 6 Hotspot 的性能

  • Charles Humble
  • 张龙

2008 年 5 月 12 日

话题:Java语言 & 开发架构

Sun 公司的 Kohsuke Kawaguchi 考察了 Hotspot JIT 在 JDK6 u10 b14 debug 版中产生的汇编代码,并将其记录在博客中。该博文着重阐述了 Java 优化的程度。

Kawaguchi 将重点放在两个主要的地方。首先是循环展开(loop unrolling),它是这样一种技术:复制循环的每次迭代所调用的指令以构成一个序列。通过减少循环中计算机需要执行的指令,节省了执行时间。JIT 将其与预处理和事后分析相结合,同时 Kawaguchi 对此的补充也说明了这样的事实:编译器已从循环的快速执行部分当中移除了一个冗余的数组索引检查。此外,结果汇编代码证明了特定于处理器的优化程度如何。例如,Kawaguchi 谈到了下面的代码:

private static byte[] foo() {

    byte[] buf = new byte[256];

    for( int i=0; i<buf.length; i++ )

        buf[i] = 0;

    return buf;

}

所产生的汇编结果使用了特定于 AMD64 芯片的 R8-R15 通用寄存器汇编代码。

其次是围绕着锁(locks)而进行的优化。在 Java 中非竞态锁的获取在不断地改进,而竞态锁的获取却一直存在问题。这个领域的工作还在持续进行中,但是 Kawaguchi 的工作却说明了几个已经得到改进的地方。 

这篇文章展示了该 Hotspot 编译器很多其他的特性,包括强大的内联——James Gosling 注意到一篇相关的博文中说“甚至连存储分配和初始化都需要内联”。这一层级的侵略性(aggression)是可能存在的,部分原因在于 JVM 会在必要时做一些潜在不安全的优化。Charles Nutter 在今年初参加 Lang.NET 大会时曾对此提出了一个很好的解释。他也强调了这项工作与 JRuby 的关系,以及与任何面向 JVM 的语言的关系。

“过去 JVM 有多种不同的能力去动态优化和再优化代码……或许最重要的是必要时的动态“逆优化(deoptimize)”。在处理性能问题时,逆优化(Deoptimization)令人非常兴奋,因为这意味着你可以进行更多的侵略性优化——对整个应用不确定的未来的潜在的不安全的优化——知道你可以在安全的路径上回退。一旦你几次遇到相同的路径,你就可以内联整个调用路径。除非明显需要,你可以忽略同步保护。你还可以在发现问题之后改变使用的优化集……本质上,在运行过程中你可以安全的“出错”并且从错误中学习。这就是为什么在特定的基准上 Java 超越了 C 和 C++ 以及最终在几乎所有基准上它都能将超越 C 和 C++ 的主要原因。同时这也是我们的 JRuby 与微软的 IronPython 和 DLR 相比,只需要做很少的事情就可以获得可接受的性能的一个关键原因。”  

从理论上讲,像 Java 这样的解释型语言的性能很有可能最终将超越编译型语言,因为它可以在运行时基于现有硬件进行优化,同时 Java 中不断提高的对特定于处理器的优化确实令人非常兴奋。对于面向 Java 平台的开发者来说,一个额外的好处在于随着新版本 Java 编译器的发布,代码的性能会不断改进,而无需对应用的源码做任何更改。

查看英文原文:Java 6 Hotspot Performance

Java语言 & 开发架构