Java 仮想マシン (JVM) では複数のチューニング手段が外部化されており、 WebSphere Business Integration アプリケーションのパフォーマンスを向上させるために使用できます。これらの手段は、ガーベッジ・コレクション、スレッド化、ヒープ・サイズ、およびロックに関連する事項を制御します。InterChange Server Express サーバーとそのコンポーネント (マップ、コラボレーション)、およびほとんどのアダプターは Java で作成されているため、InterChange Server Express アプリケーションによって実現されるパフォーマンスには JVM のパフォーマンスが大きく影響します。
このセクションでは、ガーベッジ・コレクション、ヒープ・サイズ、およびスレッドのスタック・サイズに関して発生する可能性のある問題について説明します。JVM オプションの概要については、 URL http://java.sun.com/docs/hotspot/VMOptions.html を参照してください。
URL http://java.sun.com/docs/hotspot/PerformanceFAQ.html#20 には、HotSpot エンジンに関する有用な FAQ が記載されています。
IBM JVM の詳細な説明については、「IBM Systems Journal」 Vol. 1, 2000 の Java パフォーマンス問題 (http://www.research.ibm.com/journal/sj39-1.html) を参照してください。
ガーベッジ・コレクションは、JVM にある未使用のオブジェクトを解放し、ヒープの一部を再利用できるようにする処理です。
ガーベッジ・コレクションは、メモリーが要求され、ヒープで使用可能な空きメモリーではその要求を満たすことができない場合 (割り振り失敗) に行われます。ガーベッジ・コレクションは、Java クラス・ライブラリー System.gc() が呼び出された場合にも行われます。この場合、ガーベッジ・コレクションは即時かつ同期的に行われます。
SUN HotSpot と IBM ガーベッジ・コレクターによって提供される機能は同じですが、基となるテクノロジーが異なります。いずれの JVM においても、ガーベッジ・コレクションはマーク、スイープ、およびオプションの圧縮の 3 段階で行われます。
Sun HotSpot エンジンが世代別コレクターであるのに対し、IBM JVM は世代別コレクターではないため、ガーベッジ・コレクションの各段階の実装は異なっています。HotSpot 世代別コレクターの詳細については、 URL http://java.sun.com/docs/hotspot/gc/index.html を参照してください。
IBM JVM では、ヒープがすべて消費された後にガーベッジ・コレクションが起動されます。最初の段階では、収集する領域で参照されているオブジェクトをすべてマークし、参照されていないオブジェクトをマーク解除している状態とし、それらが占有するスペースを収集して再利用できるようにしておきます。マーク段階の後、メモリーの空いているチャンクをフリー・リストに追加します。この段階をスイープと呼びます。パフォーマンス上の理由から、 IBM JVM は 512 バイトを超えるヒープ・スペースのチャンクのみを解放します。
スイープ段階の後、場合によっては圧縮段階が実行されます。圧縮段階では、オブジェクトを近くに移動して隣接する空きチャンクが大きくなるようにします。圧縮には時間がかかるため、可能な場合は避けてください。ほとんどの System.gc() 呼び出しでは圧縮が実行されます。IBM JVM は圧縮を避けるように最適化されています。
マルチスレッド化されているガーベッジ・コレクションの段階および並行化されているガーベッジ・コレクションの段階を以下の表に示します。並行とは、アプリケーション・スレッドの実行を継続したまま処理を実行することを意味します。処理が並行化されていない場合は、ガーベッジ・コレクションの段階でプログラムが休止します。
JVM リリース | タイプ | マーク | スイープ | 圧縮 |
---|---|---|---|---|
Sun HotSpot 1.3.1 | マルチスレッド対応 | なし | なし | なし |
Sun HotSpot 1.3.1 | 並行化 | なし | なし | なし |
IBM JVM 1.3.1 | マルチスレッド対応 | 可 | 可 | なし |
IBM JVM 1.3.1 | 並行化 | オプション | なし | なし |
verbosegc トレースは、ガーベッジ・コレクションのアクションおよび統計を stderr に書き込みます。verbosegc トレースは、 Java ランタイム・オプション -verbose:gc を使用してアクティブ化します。-verbose:gc の出力は、Sun HotSpot および IBM JVM では異なります。verbosegc トレースの出力例を以下に示します。この出力例には、IBM JVM および Sun HotSpot の両方について主要な情報の説明も含まれています。
<AF[8]: Allocation Failure. need 1572744 bytes <-amount of memory requested, 5875 ms since last AF> <AF[8]: managing allocation failure, action=1 (23393256 <-free at alloc failure)/131070968 <- heapsize) (2096880/3145728)> <GC: Tue Dec 18 17:32:26 2001 <GC(12): freed 75350432 bytes in 168 ms <- duration of GC, 75% free (100840568 <-free)/134216696 <- total heapsize)> <GC(12): mark: 129 ms, sweep: 39 ms, compact: 0 ms <-compact did not run> <GC(12): refs: soft 0 (age >= 32), weak 0, final 0 <-no finalizers, phantom 0> <AF[8]: completed in 203 ms>
[GC 325816K->83372K(776768K), 0.2454258 secs <-duration of GC] [Full GC 267628K->83769K <- live data (776768K <-size of heap), 1.8479984 secs]
このセクションでは、ほとんどの WebSphere Business Integration Server Express 構成に適した Java ヒープ・サイズを決定するためのガイドラインを示します。
多くのアプリケーションでは、IBM JVM のデフォルトのヒープ・サイズ設定で十分なパフォーマンスが得られます。一般に、HotSpot JVM のデフォルト・ヒープおよび新しい世代領域のヒープ・サイズは小さすぎます。
レート・トリガーによって効果的にヒープを拡大するには、-ms を 64MB または 96MB に設定し、-mx を 256 から 512MB に設定します。-mx でヒープのページングを強制しないでください。JVM は、ヒープの拡大および縮小によって GC 時間を制御しようとします。-verbose:gc の出力で GC アクションをモニターします。
同様の処理は HotSpot ヒープの設定にも使用できます。最小および最大ヒープ・サイズを設定するとともに、新しい世代領域のヒープ・サイズもヒープ・サイズの約 1/4 に増加させてください。
ヒープ・サイズが設定されると、verbose:gc トレースは GC アクションをモニターします。GC での時間のパーセンテージが高すぎ、ヒープが最大値まで拡大している場合は、-mx を増加させます。
実行中の Java プログラムには、それぞれヒープが関連付けられます。全 Java ヒープ・サイズと他の仮想メモリーの総使用量の合計が物理メモリーのサイズを超えると、ヒープがページングされ、パフォーマンスが低下します。ページングを最小化するには、以下のガイドラインを使用してください。
java.lang.OutofMemoryError は、さまざまな状況で JVM によって使用されます。この例外は、オブジェクトのために十分なヒープ・スペースがヒープにない場合や、Java ヒープ外の他のリソースが使い尽くされた場合に発生します。
java.lang.OutofMemoryError からの出力を参照し、問題の原因がヒープのメモリー不足かどうかを調べます。その場合は、ヒープのサイズを増加させます。
ヒープが十分に大きいと考えられる場合は、-verbose:gc のファイナライズされたカウントを確認します。カウントが高いと考えられる場合は、ヒープ外のリソースがヒープ内のオブジェクトによって保持され、ファイナライザーによってクリーンアップされた可能性があります。ヒープのサイズを削減し、ファイナライザーを実行する頻度を増加させてください。
IBM JVM スレッド化および同期コンポーネントは、AIX POSIX 準拠 Pthread の実装に基づいています。多くの場合、以下の環境変数によって Java のパフォーマンスが向上することが分かっており、本書のベンチマークでも使用しています。これらの変数は、 AIX ネイティブ・スレッドへの Java スレッドのマッピングを制御し、マッピング情報をオフにし、Mutex ロック時のスピンに対応します。
AIX 固有の Java チューニングについて詳しくは、 http://tesch.aix.dfw.ibm.com/java/perftips.html を参照してください。
Sun HotSpot JVM は、サーバーとして稼動するようにもクライアントとして稼動するようにも構成できます。サーバーとして構成すると、JIT (Just-In-Time コンパイラー) は、余分なプロセッサー・サイクルおよびメモリーを使用し、高度に最適化されたコードを作成します。InterChange Server Express は長時間実行されるプロセスであるため、初期インスタンス化で JIT 処理にかかった余分な時間およびメモリーのコストは、実行時のパフォーマンス向上として十分に回収できます。
したがって、Sun HotSpot JVM を使用する場合は、必ず InterChange Server Express をサーバーとして実行してください。これを行うには、InterChange Server Express プロセスの起動に -server パラメーターを追加します。
InterChange Server Express スレッド化のセクションで説明したように、Java スレッドはヒープのメモリーを消費します。さらに、スレッド自体もスレッド・スタック用に仮想メモリーを使用します。構成で過剰に多くのスレッドを使用すると、両方の場所のメモリーが問題の原因となる場合があります。JVM では、所定の量の仮想メモリーをスレッド・スタック用に確保するように構成できます。デフォルトのスレッド・スタック・サイズは、JVM のバージョンおよびオペレーティング・システムによって異なります。しかし、値を設定する機構は同じです。スタック・サイズ・サイズを 128KB に設定するには、JVM の起動時にパラメーター -ss128k を渡します。この値は十分に大きく設定してください。各スレッド・スタックには少なくとも 128KB を割り当てることをお勧めします (これより低い設定値でもシステムが正常に動作する場合もあります)。
メモリー関連の問題については、以下の SAP Note を参照してください。