前へ     目次     索引     DocHome     次へ     
iPlanet Application Server パフォーマンスおよびチューニングガイド



第 5 章   Java 実行時システムのチューニング


アプリケーションのスレッドを Solaris® ユーザレベルのスレッドにバインドすると、Java 実行時システムをチューニングできます。Solaris のオペレーティング環境は、デフォルトでは、2 つのレベルのスレッドモデルをサポートします。アプリケーションレベルの Java スレッドはユーザレベルの Solaris スレッドにマッピングされ、制限のあるライトウェイトプロセス (LWP) プール上で多重化されます。システムのプロセッサと同じ数の LWP があるだけで、カーネルリソースの保存とシステム効率の向上が可能になることがよくあります。これは、ユーザレベルスレッドが何百もある場合に役立ちます。

この章では、次のトピックについて説明します。



バインドされたスレッドの使い方

アプリケーションスレッドと Solaris lwps を 1 対 1 でバインドすることもできます。スレッドがわずかしかなく、作成される lwps も少ない場合、アプリケーションによっては、デフォルト以外のモデルを使うとパフォーマンスが向上することがあります。JVM の設定によって Java スレッドを Solaris スレッドにバインドした後に、KJS シェルスクリプト内で KJS 実行可能コマンドを呼び出すことができます。

_JVM_ARGS="bound_threads"

export _JVM_ARGS



メモリと割り当ての管理



ツールを効率的に実行するには、メモリとガベージコレクションの管理がきちんと行われている必要があります。この節で扱うトピックでは、メモリと割り当て機能の最適化に必要な情報について説明します。

この節では、次のトピックについて説明します。


ガベージコレクタのチューニング

新しい Java ランタイム環境 (JRE) には、世代別オブジェクトメモリシステムと高性能のガベージコレクションアルゴリズムが備わっています。

世代別メモリシステムでは、ヒープを適切なサイズのパーティション数個に分割します。これを世代と呼びます。世代別メモリシステムの効率は、ほとんどのオブジェクトの寿命が短いことに基づいています。新しく割り当てられたオブジェクトは、Eden とも呼ばれる若い世代に割り当てられます。新しく割り当てられたオブジェクトの死亡率は高いので、若い世代の掃除つまりガベージコレクションは生産的であることが多く、割り当てスペースの回転率が上がります。

ガベージコレクタをコンパクトにする場合は、Eden で 2 つのセミスペースを使い、存続するオブジェクトを一方の若いスペースから次のスペースにコピーします。複数の若いスペースコレクションで生き延びるオブジェクトは終身権を得ます。つまり、終身世代にコピーされます。終身世代は規模が大きく、すぐにいっぱいになることはありません。そのため、終身世代ではガベージコレクションがそれほど頻繁に行われず、各コレクションには若いスペースだけのコレクションよりも長い時間がかかります。終身スペースのコレクションはフル GC コレクションとも呼ばれます。

頻繁に行われる若いスペースのコレクションは短時間 (数ミリ秒) で終了し、たまに行われるフル GC は比較的時間がかかります (数十ミリ秒から数秒間、ヒープサイズによって異なる)。

Train アルゴリズムなど、ほかのガベージコレクションアルゴリズムは増分的で、フル GC がいくつかの増分区分に区切られます。このため、フル GC が始まると小さなガベージコレクションが停止する可能性が高くなります。オーバーヘッドを伴うので、通常、企業向けの Web アプリケーションには使われません。

通常、永続世代と呼ばれる第三世代も JVM により作成され、読み込まれた Java クラスなどの内部オブジェクトに格納されます。

HotSpot と Solaris JDK のどちらにも世代別ガベージコレクションシステムがあります。増分性のある Train ガベージコレクタは、HotSpot だけに同梱されています。HotSpot は、Solaris および NT の両方のプラットフォームのデフォルトです。将来、JDK 1.4 には新しい並列で同時的なコレクタが導入されます。

HotSpot と Solaris JDK はどちらもスレッドローカルなオブジェクト割り当てプールを使って、ロックしない、高速でスケーラブルなオブジェクト割り当てを行います。ユーザアプリケーションレベルのオブジェクトプールは、以前の世代の Java 仮想マシンで実行すると実際には利点があることもあります。しかし、JDK 1.2 以後で使用できる新しい世代の仮想マシンでは、実際はアプリケーションの速度が低下することもあります。オブジェクトの構築に非常に手間がかかり、しかも重要と考えられる場合にだけ、実行プロファイルでのプールを検討します。


ガベージコレクタの設定値の指定

ガベージコレクタによってメモリ使用率を向上させるために、次の設定値を使用できます。

  • 明示ガベージコレクタ

  • 遅延ガベージコレクタ


明示ガベージコレクタ

明示ガベージコレクタの動作を変更することで、アプリケーションサーバによるメモリ使用率を制御できるようになります。Solarisの iasenv.ksh ファイル内にある JAVA_GX_ARGS=-DGX.cleaner.enabled キー、また Windows のレジストリの設定を変更することで、クリーナを有効にしたり無効にしたりできます。

Solaris では、リクエストの応答時間を速くするために、JAVA_GX_ARGS=-DGX.cleaner.enabled エントリがデフォルトで「no」に設定されています。iPlanet Application Server のメモリ使用率が異常に高いことが判明した場合は、この値を「yes」に変更してクリーナを有効にするか、または JAVA_GX_ARGS ラインをコメント出力します。

JAVA_GX_ARGS=-DGX.cleaner.enabled=yes

クリーナは、いったん有効にされると 10 秒ごとに呼び出されます。クリーナの呼び出し間隔は、次のラインを iasenv.ksh ファイルに追加して制御できます。

JAVA_GX_ARGS=-DGX.cleaner.interval=N
この N は、ミリ秒数です。

Windows では、クリーナはデフォルトで有効にされています。パフォーマンスを向上させるために、クリーナを無効にしたり、クリーナの呼び出し間隔を長く設定することができます。

クリーナのデフォルトの動作を変更する場合は、
SOFTWAREiPlanetApplication Server6.0Java にあるレジストリ内の JavaArgs に、次のフラグを追加します。

-DGX.cleaner.doGC=yes -DGX.cleaner.interval=N

上記の N は、ミリ秒数です。


遅延ガベージコレクタ

メモリ使用率の監視をするアプリケーションに基づいた AppLogic 用の遅延ガベージコレクタを有効にするために、新しいスイッチが導入されました。この導入によって、Java システムの useDeferredGC プロパティを設定してチューニングすることができます。

Solaris では、iasenv.ksh ファイル内にある次の JAVA_ARGS を追加することで、遅延ガベージコレクタを有効にできます。

-DuseDeferredGC=true

Windows では、SOFTWAREiPlanetApplication Server6.0Java にあるレジストリ内の次の JavaArgs エントリを追加します。

-DuseDeferredGC=true

AppLogic ベースのアプリケーションではメモリ使用率が急に増加する場合が少ないことが報告されているため、このプロパティのデフォルト値は「false」に設定されています。遅延ガベージコレクションでは、ガベージがコレクションされないように、新しく作成されたオブジェクトの参照がリクエストの実行の最後まで一時的に格納されます。したがって、リクエストの最後ですべてのメモリが一度に解放されますが、過渡的にメモリ使用率が上がることがあります。


ガベージコレクションの追跡

JVM に -verbose:gc フラグ (-verbosegc の場合もある) を立てると、コレクションのたびに 1 行の通知メッセージが出力されます。いくつかの理由から、このフラグを立てると便利です。

  • ガベージコレクションの停止と停止時間が必ずログに記録され、異常に長く停止しているかどうかが検出されます。

  • また、JVM の生存を表す「心臓の鼓動」のような役目を果たします。

    アプリケーションロジックがデッドロックされている場合でも、通常のガベージコレクションが行われる可能性があるので注意が必要です。

  • アプリケーションが Java オブジェクトをリークしているかどうかが非常に簡単にわかります。多くのフルガベージコレクションが行われた後でも非ガベージオブジェクトの数が増える場合は、メモリリークの疑いがあります。


Java ヒープのチューニング

世代別ガベージコレクションについて理解できたので、ヒープ設定がパフォーマンスに影響を与える理由はすぐにわかります。

この節には次のトピックがあります。


Java ヒープのサイジングのガイドライン

Java ヒープのサイジングにとって重要なガイドラインがあります。

  • 各 JVM プロセスに付与する Java ヒープを決定します。

    まず、アプリケーションサーバノードで使用するシステムメモリの量を決定します。次に、KJS プロセス数を設定し、システムメモリのサイズをこの数で割ります。それぞれの KJS プロセスが JVM プロセスです。

    KJS プロセスと CPU 数との比率は、およそ 1 対 1 です。比率を多少変えて試してみることができます。

  • Java ヒープの開始サイズと最大サイズを、上で決定したサイズに設定します。JVM フラグの -Xms<size> および -Xmx<size> は最小ヒープサイズと最大ヒープサイズです。詳細については、JVM のマニュアルを参照してください。

たとえば、-Xms64m -Xmx64m のヒープサイズは 64 MB です。開始ヒープサイズ (-Xms) と最大許容ヒープサイズ (-Xmx) を同じ値にすると利点があります。JVM がデフォルトの開始ヒープサイズで始動するように指定された場合は、ヒープサイズが自動的に拡張します。ただし、この拡張は低速のプロセスであり、このヒープ拡張段階の間に頻繁にガベージがコレクションされてパフォーマンスが低下します。

規模の大きい Eden や若い世代スペースであれば、フルガベージコレクション間にスペースが増加します。しかし、若いスペースのコレクションには比較的時間がかかります。一般に、Eden のサイズは最大ヒープサイズの 1/4 から 1/2 にしておくことができます。


HotSpot サーバ VM のチューニングオプション

特に指定しないかぎり、iPlanet Application Server 6.5 では 1.3 Hotspot Server VM が読み込まれます。サーバ側のアプリケーションにとって、サーバモードの VM がより適しています。iPlanet Application Server は、次の引数でチューニングされた VM で始動します。

-server -Xss512k -Xms128m -Xmx1024m -XX:NewSize=42m -XX:MaxNewSize=342m

-Xconcurrentio -XX:+DisableExplicitGC

利用可能な物理的なメモリサイズに基づいて、ヒープサイズを増やしたり減らしたりすることができます。

これらのオプションはアプリケーションによってはよく機能しますが、あまりよく機能しないアプリケーションもあります。つまり、I/O バインド型、計算集約型、メモリ集約型などのアプリケーションのタイプに左右されます。最適なオプションを決定する前に、調整可能なパラメータを試してみる必要があります。

表 5-1 に、VM のオプションと説明を示します。


表 5-1    HotSpot サーバ JVM のチューニングオプション

VM オプション

説明

-XX:NewSize=<n>  

新世代の最初のサイズ (バイト数)  

-XX:MaxNewSize=<n>  

新世代の最大サイズ (バイト数)  

-XX:+DisableExplicitGC  

GC の全体的な制御下で GC、VM の明示した呼び出しを無効にする  

-Xconcurrentio  

スレッドベースの同期化の代わりに LWP ベースの同期化を行う  

-XX:CompileThreshold=<n>  

「n」は Hotspot コンパイラによって将来、最適化が実行された後のメソッドの呼び出し数。サーバモードの場合のデフォルト値は 10,000、クライアントモードの場合は 1,500  

-Xbatch  

バックグランドのコンパイルを無効にする  

-Xincgc  

増分性のあるガベージコレクション  

若い世代のサイズを定数に設定すると、サイズの変更ができません。当社のテストでは、増分性のある GC を使用するとスループットが低下することが判明しました。

JVM のチューニングについては、http://java.sun.com/docs/hotspot/index.htm を参照してください。


Solaris でのヒープ設定の例

KJS シェルスクリプトで次の引数を JAVA_ARGS 環境変数に追加します。

-Xgenconfig:64m,64m,semispaces:64m,512m,markcompact

これにより、若い世代用の 64 MB セミスペースが 2 つある 512 MB の Java ヒープが作成されます。記号と簡易アルゴリズムを使うよう指定します。若い世代のサイズもヒープ全体のサイズも大きくすることができます。Solaris JDK では、オブジェクトヘッダやほかのスペースオーバーヘッドを占めることを正当化して、各セミスペースに指定したサイズの 2 倍のサイズを割り当てています。

-Xgenconfig は正しく理解しにくい複雑なフラグです。JVM の内部的な記事以外はあまり公表されず、文書化されていません。

-Xgenconfig, -Xms, -Xmx フラグは明らかに相互的であり、genconfig とともに指定されると、ほかの設定値に優先します。ただし、ある種の範囲のチェックでは、genconfig に指定された値と最小値および最大値が確実に一貫するように、JVM によって実行されるように見えます。


Windows でのヒープ設定の例

次のプロパティを iPlanet のレジストリに設定して、引数を JVM に渡すことができます。

HKEY_LOCAL_MACHINESOFTWAREiPlanetApplication Server6.0JavaJavaArgs を希望する文字列に設定します。これがヒープサイジングパラメータを設定する場所です。

-Xms フラグと -Xmx フラグは、Solaris JDK の場合と同様に設定する必要があります。

-XX:NewSize=<size> で、新しいオブジェクトを割り当てる若いオブジェクトスペースの初期サイズをバイト数で指定します。若いスペースの初期サイズはデフォルトで 2 MB です。初期サイズは、1024 の倍数にする必要があります。キロバイトの場合は k または K を、メガバイトの場合は m または M を付けます。-XX:NewSize=64m の場合、若いスペースの初期サイズが 64 MB に設定されます。若いスペースのサイズが大きいと、ガベージコレクションで停止する時間が長くなります。

-XX:MaxNewSize=<size> は、新しいオブジェクトを割り当てる若いオブジェクトスペースの最大サイズをバイト数で指定します。若いスペースの初期サイズは 2 MB です。MaxNewSize1024 の倍数で、2MB 以上であることが必要です。キロバイトの場合は k または K を、メガバイトの場合は m または M を付けます。MaxNewSize のデフォルト値は 64 MB です。-XX:MaxNewSize=128m を使って、若いスペースを必要に応じて 128 MB まで拡張することができます。

-XX:SurvivorRatio=k では、Eden のサイズ比率を生存スペースのサイズに設定します。たとえば、Windows でのデフォルト比率が 8 であれば、NewSize=64m の場合は 4 MB のセミスペースが 2 つになります。NewSizeSurvivorRatio を使うと、セミスペースを必要なサイズにすることができます。

このフラグは、内部的なサイジングの計算をかなり混乱させるので、最後の手段として使用することをお勧めします。


デフォルトの設定に比べて、-Xms256m -Xmx256m -XX:NewSize=128m -XX:MaxNewSize=128m などの設定ではパフォーマンスが 30% 向上したという報告があります。NewSizeMaxNewSize を正しく設定するだけでも、パフォーマンスに大きな影響を与えることができます。



このような HotSpot フラグは、HotSpot ベースのすべての Java ランタイム環境で使用することができます。HotSpot ベースの JDK 1.3 は、Solaris、Windows、および Linux でデフォルトとして提供されています。HotSpot のすべてのパフォーマンスフラグが、http://java.sun.com/docs/hotspot/VMOptions.html に一覧表示されています。


ダイナミックコンパイラのチューニング

Windows と Solaris JDK 1.3.1 の Java HotSpot 1.3 はどちらも適応型ダイナミックコンパイラを実装しており、プログラムのホットスポットを検出してピークパフォーマンス時のホットなプログラムセグメントだけをコンパイルします。このプロファイルによるコンパイルを行う場合、アプリケーション起動時に短時間のパフォーマンスの増加が見られることがあります。このため、ウォームアップの済んだ iPlanet Application Server でベンチマーク測定を行う場合は注意してください。

JIT をオフにすると時間がかかります。JIT をオフにして、よくチューニングされたシステム設定でアプリケーションを使った場合、3 倍のパフォーマンスが測定されたことがあります。これは、アプリケーションの性質やハードウェアとデータベース設定のシステムボトルネックによって異なります。

次の場合は、ダイナミックコンパイラをオフにすることができます。

  • デバッグ中に、ソース行番号がある Java 例外スタック追跡を出力して確認する場合

  • ダイナミックコンパイラでまれに発生するバグに対処する場合

    この場合は、JVM の隠し引数があり、クラスでコンパイルするメソッドの一部または全部を選択的に無効にすることができます。詳細は、Sun Java サポートにお問い合わせください。

Windows でコンパイラをオフにする必要がある場合は、レジストリの JavaArgs プロパティに -Xint を追加します。Solaris では、KJS シェルスクリプトの JAVA_ARGS-Djava.compiler=none を追加します。


前へ     目次     索引     DocHome     次へ     
Copyright © 2002 Sun Microsystems, Inc. All rights reserved.

最新更新日 2002 年 3 月 6 日