Java HotSpot™仮想マシンのパフォーマンスの向上

階層型コンパイル

Java SE 7で導入された階層型コンパイルによって、サーバーVMへのクライアント起動が短縮されます。通常、サーバーVMはインタプリタを使用して、コンパイラに渡されるメソッドについてのプロファイリング情報を収集します。階層型方式では、インタプリタに加えてクライアント・コンパイラを使用してコンパイル・バージョンのメソッドが生成され、それらが自身のプロファイリング情報を収集します。コンパイルされたコードはインタプリタよりもはるかに高速なため、プログラムのプロファイリング段階の実行パフォーマンスが大きく向上します。サーバー・コンパイラによって生成される最終コードをアプリケーション初期化の早い段階で利用できる可能性があるため、多くの場合クライアントVMでの起動速度を向上させることができます。また、階層型方式ではプロファイリング段階の高速化によってプロファイリングにかけられる時間が長くなるため、通常のサーバーVMよりも優れたピーク・パフォーマンスを実現でき、最適化の向上にもつながる可能性があります。

階層型コンパイルはサーバーVMのデフォルト・モードです。32ビットと64ビットの両方に加え、圧縮OOPがサポートされます(次のセクションを参照)。階層型コンパイルを無効にするには、javaコマンドで-XX:-TieredCompilation フラグを使用します。

圧縮OOP

Java HotSpotの専門用語である「OOP」(Ordinary Object Pointer)は、オブジェクトへの管理ポインタです。OOPは通常、ネイティブ・マシン・ポインタと同じサイズ(LP64システムでは64ビット)です。ILP32システムでは、最大ヒープ・サイズは4Gバイトよりやや少なく、これは多くのアプリケーションにとって十分ではありません。LP64システムでは、指定されたプログラムが使用するヒープが、ILP32システムで実行する場合よりも約1.5倍大きくなることがあります。これほど必要なのは、管理ポインタのサイズが増大することが原因です。メモリーのコストは低いですが、最近では帯域幅およびキャッシュが不足しているため、4Gバイト制限を解決するためだけにヒープ・サイズが大幅に増加するのは望ましくありません。

Javaヒープ内の管理ポインタは、8バイト・アドレス境界に整列されたオブジェクトを指します。圧縮OOPは、(JVMソフトウェア内のすべてではないものの多くの場所で)管理ポインタを、64ビットJavaヒープ・ベース・アドレスからの32ビット・オブジェクト・オフセットとして表します。これらはバイト・オフセットではなくオブジェクト・オフセットのため、最大40億のオブジェクト (バイトではありません)、または最大約32Gバイトのヒープ・サイズをアドレス指定するために使用できます。これらを使用して参照先オブジェクトを見つけるには、これらを8倍してJavaヒープ・ベース・アドレスに加算する必要があります。圧縮OOPを使用するオブジェクト・サイズは、ILP32モードのそれに匹敵します。

デコードという語は、32ビット圧縮OOPが管理ヒープ内の64ビット・ネイティブ・アドレスに変換される処理を表すのに使われます。この逆の処理は、エンコードと呼ばれます。

圧縮OOPはJava SE 6u23以降でサポートされ、デフォルトで有効になっています。Java SE 7では、-Xmxが指定されていないときの64ビットJVMプロセスおよび-Xmxの値が32Gバイト未満の場合に、デフォルトで圧縮OOPが使用されます。6u23リリースより前のJDK 6でこの機能を有効にするには、javaコマンドで-XX:+UseCompressedOopsフラグを使用します。

ゼロ・ベース圧縮OOP (Ordinary Object Pointer)

64ビットJava仮想マシン・プロセスで圧縮OOPを使用する場合、JVMソフトウェアは、仮想アドレス・ゼロから始まるメモリーをJavaヒープ用に予約するようにオペレーティング・システムに要求します。オペレーティング・システムがこのような要求をサポートしていて、Javaヒープ用のメモリーを仮想アドレス・ゼロで予約できる場合、ゼロ・ベース圧縮OOPが使用されます。

ゼロ・ベース圧縮OOPを使用することは、Javaヒープ・ベース・アドレス内で加算することなく、64ビット・ポインタを32ビット・オブジェクト・オフセットからデコードできることを意味します。ヒープ・サイズが4Gバイト未満の場合、JVMソフトウェアはオブジェクト・オフセットの代わりにバイト・オフセットを使用できるため、オフセットを8倍にすることも回避できます。64ビット・アドレスを32ビット・オフセットにエンコードすると、それだけ効率的になります。

Javaヒープ・サイズが26Gバイト程度の場合は、Solaris、Linux、およびWindowsオペレーティング・システムでは通常、Javaヒープを仮想アドレス・ゼロに割り当てることができます。

エスケープ解析

エスケープ解析は、Java Hotspot Serverコンパイラが新規オブジェクトの使用スコープを解析し、それをJavaヒープに割り当てるかどうかを決定するための技術です。

エスケープ解析はJava SE 6u23以降でサポートされ、デフォルトで有効になっています。

Java Hotspot Serverコンパイラは、次に記述する、フローインセンシティブ・エスケープ解析アルゴリズムを実装します。

 [Choi99] Jong-Deok Choi, Manish Gupta, Mauricio Seffano,
          Vugranam C. Sreedhar, Sam Midkiff,
          "Escape Analysis for Java", Procedings of ACM SIGPLAN
          OOPSLA  Conference, November 1, 1999

エスケープ解析に基づき、オブジェクトのエスケープ状態は次のいずれかになる可能性があります。

エスケープ解析のあとサーバー・コンパイラは、スカラー置換可能オブジェクト割当ておよび関連付けられたロックを、生成されたコードから除去します。また、サーバー・コンパイラは非グローバルにエスケープするすべてのオブジェクトのロックも除去します。ヒープ割り当てを、非グローバルにエスケープするオブジェクトのスタック割当てで置き換えることはありません

エスケープ解析のいくつかのシナリオを次で説明します。

NUMAコレクタの拡張機能

Parallel Scavengerガベージ・コレクタは、NUMA (Non Uniform Memory Access)アーキテクチャを持つマシンを利用できるように拡張されています。最新のほとんどのコンピュータは、メモリーの異なる部分にアクセスするためにかかる時間が異なる、NUMAアーキテクチャをベースにしています。通常、システム内の各プロセッサには、アクセス遅延時間が小さく帯域幅の広いローカル・メモリーと、アクセスがはるかに遅いリモート・メモリーが搭載されています。

Java HotSpot仮想マシンでは、NUMA対応アロケータがこのようなシステムを利用するために実装されており、Javaアプリケーションのためにメモリー配置を自動的に最適化します。このアロケータは、若い世代のヒープのEden領域(新しいオブジェクトのほとんどが作成される)を制御します。アロケータはこの領域を、いくつかの領域(それぞれが特定ノードのメモリー内に配置される)に分割します。アロケータは、オブジェクトを割り当てるスレッドがそのオブジェクトをもっとも使用する可能性があるという仮定に依存しています。新しいオブジェクトに最速でアクセスするために、アロケータは割当て側スレッドからローカルな領域内にそれを配置します。領域は、さまざまなノードで実行されているアプリケーション・スレッドの割当て率を反映するために、動的にサイズ変更できます。これにより、単一スレッド・アプリケーションであってもパフォーマンスを向上できます。また、若い世代の「From」および「To」Survivor領域、古い世代、および永続的世代では、ページ・インターリーブが有効になっています。これにより、すべてのスレッドの、これらの領域へのアクセス遅延時間が均一になります。

NUMA対応アロケータは、Solaris(tm) 9 12/02以降のSolarisオペレーティング・システム、およびLinux kernel 2.6.19かつglibc 2.6.1以降のLinuxオペレーティング・システムで利用できます。

NUMA対応アロケータは、-XX:+UseNUMAフラグとParallel Scavengerガベージ・コレクタの選択によって有効にできます。Parallel Scavengerガベージ・コレクタはサーバークラス・マシンのデフォルトです。Parallel Scavengerガベージ・コレクタは、-XX:+UseParallelGCオプションを指定することで明示的に有効にすることもできます。

-XX:+UseNUMAフラグはJava SE 6u2で追加されました。

注: Linuxカーネルには、-XX:UseNUMAを使用して実行したときにJVMがクラッシュする既知のバグがありました。このバグは2012年に修正されたため、Linuxカーネルの最新バージョンには影響しないはずです。カーネルがこのバグを持つかどうかを確認するために、ネイティブ・リプロデューサを実行できます。

NUMAパフォーマンス・メトリック

SPEC JBB 2005ベンチマークに基づいて8チップOpteronマシンで評価したときに、NUMA対応システムは次のパフォーマンス向上を示しました。


Copyright © 1993, 2020, Oracle and/or its affiliates. All rights reserved.