Javaスレッドのやり取りは、アプリケーションのパフォーマンスに影響を与えます。この章では、Javaスレッド間の相互作用をチューニングする方法について説明します。
スレッドのやり取りをチューニングする方法は2つあります。
プログラム・コードの構造を変更します。たとえば、スレッド間の競合の回数を最小限に抑えます。
アプリケーション実行中の競合の処理方法に影響を与えるOracle JRockit JVMのオプションを使用します。
この章の内容は次のとおりです。
JRockit JVMによるスレッドおよびロックの処理方法の詳細は、『Oracle JRockit JDKの紹介』のスレッドおよびロックの概要に関する項を参照してください。
JRockitフライト・レコーダを設定して、フライト・レコーダの記録中に発生したロックと競合に関する情報を収集および分析することができます。これを行うには、アプリケーションを起動するときに次のオプションを追加します。
-XX:+UseLockProfiling
ロック・プロファイリングが有効になっている場合、JRockit Mission Control Clientの「ロック・プロファイリング」タブでJavaロックに関する情報を表示できます。
注意: ロック・プロファイリングによって、Javaアプリケーションの実行時に著しいオーバーヘッド処理(20%程度)が生じます。 |
ロック・プロファイル・カウンタに関連する2つの診断コマンドがあります。使用するには、-XX:+UseLockProfiling
オプションを指定してロック・プロファイリングを有効にする必要があります。これらはjrcmd
ユーティリティとともに使用します。
lockprofile_print
コマンドは、ロック・プロファイル・カウンタの現在の値を出力します。
lockprofile_reset
コマンドは、ロック・プロファイル・カウンタの現在の値をリセットします。
診断コマンドの詳細は、『Oracle JRockit診断およびトラブルシューティング・ガイド』を参照してください。
ファット・ロックに対するスピンは、通常は効果があります。ただし、ロックによって長い待機時間や競合の頻発が生じる場合など、状況によっては、パフォーマンスの点でコストがかかる可能性があります。次のオプションを指定して、ファット・ロックに対するスピンを無効にし、パフォーマンス低下の可能性を排除することができます。
-XX:-UseFatSpin
このオプションは、Javaのファット・ロック・スピン・コードを無効にし、ファット・ロックを取得しようとするスレッドが直接スリープ状態に入れるようにします。
スレッドがファット・ロックをスピンするか、スピンしない(ロックが取得できない場合に直接スリープ状態に入る)かをJVMに決定させることができます。
適応性のあるロック・スピンを有効にするには、-XX:+UseAdaptiveFatSpin
オプションを使用します。
デフォルトでは、ファット・ロックに対する適応性のあるスピンは無効になっています。特定のファット・ロックを取得できないスレッドがスピンとスリープのどちらの状態に入るかは、実行時に変更できます。
ファット・ロックにおける競合の数が少ない場合、そのロックはシン・ロックに変換されます。このプロセスを「ロックの引下げ」と呼びます。シン・ロックでは競合していないロックのパフォーマンスが向上します。このため、ロックの引下げはデフォルトで有効になっています。
ファット・ロックを引き下げない場合は、次のオプションでアプリケーションを実行します。
-XX:-UseFatLockDeflation
ロックの引下げが無効になっている場合、ファット・ロックは、ロックの取得を待機しているスレッドがなくなっても、ファット・ロックのままとなります。
ロックの引下げをトリガーするタイミングをチューニングすることもできます。次のオプションで、引き下げるまでに発生する必要のある、競合しなくなったファット・ロックの解除の回数を指定します。
-XX:FatLockDeflationThreshold=NumberOfUnlocks
遅延ロック解除は、非共有ロックを多用するアプリケーションを対象としています。多数の共有ロックを使用するアプリケーションでは、それらのロックの生存期間が短い場合でも、このオプションを設定するとパフォーマンスの低下を招くことがあるので注意が必要です。
遅延ロック解除が設定されていると、重要なセクションの実行が終了してもその時点ではロックは解放されません。そのため、ロックが一度取得された後で、次にそのようなロックを取得しようとするスレッドは、そのロックがすでに解放されているか、または解放可能であることを確認する必要があります。この確認は、最初のスレッドがその時点でまだロックを使用し続けているかどうかを調べることによって行われます。共有ロックは通常のロックに変換され、遅延モードの状態は継続しません。
遅延ロック解除は、確定的ガベージ・コレクタ以外のすべてのガベージ・コレクション方式について、JRockit JVMでデフォルトで有効になっています。