川口氏は2つの主な分野を中心に取り上げている。1つ目はループの展開である。ループの展開は、それぞれのループの繰り返しの中から呼び出される命令を複数回分配置して、1回の繰り返しで行われるようにする技術である。これにより、コンピュータがループの中で実行しなければならない命令のオーバーヘッドが減り、処理にかかる時間が短縮される。JITはこれを、ウォームアップとクールダウンに組み合わせている。川口氏の解説では、コンパイラによってループの高速な部分から冗長な配列の添え字のチェックが削除されているということを明らかにしている。さらに、出力されたアセンブリコードは、プロセッサ固有の最適化がどれだけ行われているかを証明している。川口氏は、次のコードを例とした。
private static byte[] foo() {
byte[] buf = new byte[256];
for( int i=0; i buf[i] = 0;
return buf;
}
出力されたアセンブリでは、AMD64のチップに固有の汎用レジスタである、R8-R15が使用されていることにも言及している。
川口氏が調査を行った2つ目の分野は、ロックを中心とした最適化である。競合しないロックの獲得は、Javaでは長い間に着々と改善されているが、競合するロックの獲得には依然として問題がある。この分野での活動はまだ続いているが、いくつかの部分が改善されたことが川口氏の行ったことからわかる。
この記事では他にもHotspotの多くの機能を示しており、その中にはインライン展開がいかに積極的に行われているかという点も含まれている- James Gosling氏は川口氏の記事に関連したブログ記事の中で(source)「記憶域の割り当てや初期化さえもインライン展開されている」と書いている。このレベルの積極性が可能な理由のひとつは、JVMは潜在的に安全ではない最適化を必要に応じて行うことができることである。Charles Nutter氏は、今年の初めに行われたLang .NETの会議への参加について(source)の記事の中で、このことについて説得力のある説明をしている。彼の投稿では、この作用とJRuby(JVMを対象としている言語を暗に含む)との関連についても強調している。
「JVM は時間をかけてコードの動的最適化や再最適化の能力を...そして、おそらく最も重要なことですが、必要に応じてコードを動的に *非最適化する* 能力を変えてきました。パフォーマンスの問題を扱う場合、非最適化は非常に面白いことです。なぜなら、後で絶対確実で安全なパスを当てにできるとわかった上で、ずっと積極的な最適化 --アプリケーション全体の不確かな未来において潜在的に安全ではない最適化-- を行えることを意味しているからです。つまり、同一のパスを何回か見かけたら呼び出しパス全体をインライン展開する、といったことができるのです。明らかに同期化のガードが必要であるとわかるまで、あえてガードしないでおくこともできます。そして、適用された最適化のセットを後から変更することができます。...要するに、安全に「間違え」、そして実行時に失敗から学ぶことができるのです。今や特定の手作りのベンチマークではJavaがCやC++ を凌ぐものとなり、いずれは、ほとんど全てのベンチマークにおいてCやC++を超えるに違いないのは、このことが大きな理由となっています。そしてこれは、 IronPythonやDLRでMicrosoftが行ったよりもはるかに少ない作業で、JRubyから私達が受け入れられるパフォーマンスを得ることができた主な理由なのです。」
Java のようなインタプリタ言語が最終的にはコンパイル言語のパフォーマンスを凌ぐことは、理論上は常に可能である。なぜなら、利用可能なハードウェアに基づいて、実行時に最適化を行うことが可能だからである。そして、Javaにおけるプロセッサ固有の最適化の利用増大は、この点で特に面白い発展である。 Javaプラットフォームをターゲットとしている開発者達にとって重要なプラスになる点は、Javaコンパイラコードが新しくリリースされるたびに、アプリケーションのソースを変更することなく、パフォーマンスが改善されることである。
原文はこちらです:http://www.infoq.com/news/2008/05/hotspot_performance