WebSphere Application Server for z/OS, Version 6.0.x   
             オペレーティング・システム: z/OS

             目次と検索結果のパーソナライズ化

Java メモリーのチューニング・ヒント

Java 言語で作成されたエンタープライズ・アプリケーションは、 複雑なオブジェクト関係を持ち、多数のオブジェクトを使用します。Java 言語はオブジェクトのライフ・サイクルに関連したメモリーを自動的に管理しますが、アプリケーションのオブジェクト使用パターンを理解することは重要です。

特に、以下を確認してください。

こうした管理技法を適用するには、ガーベッジ・コレクションの効果について理解する必要があります。

IBM サポートの資料を利用すると、 この問題の解決に必要な情報収集の時間を節約できます。 PMR を開く前に、IBM サポート・ページを参照してください。

ガーベッジ・コレクションのボトルネック

Java ガーベッジ・コレクションをテストすることによって、 アプリケーションがどのようにメモリーを使用するかが理解できます。 ガーベッジ・コレクションは Java の強みです。アプリケーション作成者からメモリー管理の負担をなくす ことによって、Java アプリケーションは、ガーベッジ・コレクション機能を持たない言 語で作成されたアプリケーションよりも堅固になっています。ただし、この堅固さが生かされるのは、アプリケーションがオブジェクトを 過剰に使用していない場合に限ります。 ガーベッジ・コレクションは通常、適切に機能するアプリケーションの合計実行時間の 5% から 20% を消費します。管理を行わない場合、ガーベッジ・コレクションはアプリケーションにとって最大のボトルネックの 1 つになります。

Java 仮想マシン (JVM) は、並列ガーベッジ・コレクターを使用して、 Sun HotSpot 1.3.1 JVM が単一スレッドのガーベッジ・コレクターを持っている大部分のガーベッジ・コレクション・サイクルの間に、SMP を十分に活用します。

ガーベッジ・コレクションのモニター

ガーベッジ・コレクションを使用して、アプリケーションのパフォーマンスの正常 性を評価することができます。固定ワークロードの実行中にガーベッジ・コレクションをモニターすることによって、アプリケーションがオブジェクトを使いすぎているかどうかがわかります。 ガーベッジ・コレクションによって、メモリー・リークがあるかどうか検出することもできます。

ガーベッジ・コレクションのモニターの詳細については、以下を参照してください。

ガーベッジ・コレクション統計は、verbose:gc JVM 構成設定を使用してモニターできます。verbose:gc フォーマットは、異なる JVM またはリリース・レベルの間では標準化されません。 IBM verbose:gc 出力の説明については、以下を参照してください。 パフォーマンス: 学習用リソース .

このタイプの検査を行う場合は、ヒープ・サイズの最小値と最大値を 同じ値にします。ユーザー・エラーなど、実稼働環境での使用にできるだけ一致する、繰り返 しの多い代表的なワークロードを選択します。

意味のある統計値を得るには、アプリケーションが定常状態になるまで固定ワークロードを実行します。

オブジェクトの過剰使用の検出

JVM ランタイムのカウンターを監視することによって、アプリケーションがオブジェクトを乱用しているかどうかを確認できます。Java 仮想マシン・プロファイラー・インターフェース (JVMPI) カウンターを 使用可能にするには、-XrunpmiJvmpiProfiler コマンド行オプションとともに 、JVM モジュールの最大レベルも設定しなければなりません。ガーベッジ・コレクション間の平均時間は、最もよい結果が出た場合で、ガーベッジ・コレクション 1 回分の平均所要時間の少なくとも 5 から 6 倍です。この数値に達しない場合、アプリケーションがガーベッジ・コレクションに費やす時間は、実行時間の 15% を超えています。

ガーベッジ・コレクションのボトルネックを示す情報がある場合、 ボトルネックを解消する方法は 2 つあります。 アプリケーションを最適化する最も経済的な方法は、オブジェクト・キャッシュとプールをインプリメントすることです。 Java プロファイラーを使用して、ターゲットにするオブジェクトを 決定します。アプリケーションを最適化できない場合は、メモリー、プロセッサー、およびクローンの追加が役に立つことがあります。 メモリーを追加することによって、各クローンが妥当なヒープ・サイズを維 持できるようになります。プロセッサーを追加すると、 クローンを並列に実行できます。

メモリー・リークの検出

メモリー・リークは、Java 言語ではガーベッジ・コレクションのボトルネックの原因となる危険な状況です。 メモリー・リークは最終的にシステムの不安定性につながるため、メモリーの過剰使 用よりも有害です。時間が経過するにつれて、ガーベッジ・コレクションが頻繁に発生し、 最終的にはヒープが使い尽くされて、Java コードは致命的なメモリー不足例外により停止します。 メモリー・リークは、使われていないオブジェクトが参照され、解放されないときに起こります。 メモリー・リークは、Hashtable などの集合クラスでよく発生します。 これは、この表が実際の参照情報が削除された後であっても、常にオブジェクトを参照していることが原因です。

ワークロードが高いと、アプリケーションが、実稼働環境でのデプロイメント直後に破損することが頻繁に起こります。このような状況は、リークを起こしているアプリケーションで、ワークロードの高さがリークの拡大を加速し、メモリー割り振りの失敗が生じる場合に特に顕著です。

メモリー・リークのテスト

メモリー・リークをテストする目的は、数を拡大することです。 メモリー・リークはほんの数バイトから数 K バ イトの大きさにすぎないため、ガーベッジ・コレクションでは検出されません。使用可能なメモリーと使用不能なメモリー の予期されるサイズを見分けることは、微妙な作業です。 数が増大してギャップが大きくなり、矛盾を簡単に認識できるようになれば、 この作業はもっと簡単になります。以下のリストは、メモリー・リークについての重要な結論です。
  • 長期間実行するテスト

    メモリー・リークの問題は、一定の期間を経てからでないと表面化しないため、メモリー・リークは長期間実行するテストでは検出されやすいと言えます。 短期間の稼働テストでは誤った警告を受ける可能性があります。Java 言語では、いつメモリー・リークが発生しているかを認識しにくい場合があります。メモリーの使用が突然に、あるいは一定の期間内に単調に増加したように見える場合には、特に判断がむずかしいでしょう。 メモリー・リークの検出がむずかしいのは、このような増加が妥当なものであったり、開発者が意図的に行ったものであったりする可能性があるためです。 後になって使用されるオブジェクトと、まったく使用されないオブジェクトとを区別する方法は、アプリケーションを長期間実行していればわかってきます。 長期間実行するアプリケーションのテストでは、実際にオブジェクトが後になって使用されているかどうかについて、 より確信が持てるようになります。

  • 反復テスト

    多くの場合、同じテスト・ケースを続けて反復する場合に、メモリー・リークの問題が起こります。メモリー・リークのテストのゴー ルは、使用不能なメモリーと使用中のメモリーとの間で、相対的サイズに大きなギャッ プを作り出すことです。同じシナリオを何度も繰り返すことによって、このギャップは非常に累進的に増えていきます。このテストは、テスト・ケースの実行により発生するリーク数がごくわずかであるために、1 回の実行ではほとんど検出できないような場合に役立ちます。

    反復テストは、システム・レベルまたはモジュール・レベルで使用できま す。モジュラー・テストの利点は、管理の点でより優れていることです。モジュールが、専用のモジュールを保持して、メモリーの使用など外部の副次作用が発生しないように設計されている場合、メモリー・リークのテストは簡単になります。最初に、モジュールを実行する前のメモリー使用量が記録されます。次に、固定セットのテスト・ケースが 繰り返し実行されます。テスト実行の終了時には、現在のメモリー使用量が記録され、顕著な変化がないかどうかチェックされます。実際のメモリー使用量を記録するときには、ガーベッジ・コレクションを行う必要があることを覚えておいてください。これを行うには、ガーベッジ・コレクションを実行したいモジュールに System.gc() を挿入するか、このイベントを強制的に発生させるプロファイル作成ツールを使用します。

  • 並行性テスト

    一部のメモリー・リーク問題は、アプリ ケーションでいくつかのスレッドが実行中の場合にのみ起こる可能性があります。 残念なことに、プログラム・ロジックの複雑さが増したため、同期点からメモリー・リークが発生することが非常に多くなっています。プログラミング時に注意を怠ると、参照が保持されたままになったり、解放されなかったりする可能性があります。メモリー・リークの問題は、システムの並行性が 増すことによって、促進されたり、加速されたりすることがよくあります。 並行性を高める最も一般的な方法は、テスト・ドライバー内のクライアント数を増やすことです。

    メモリー・リークのテストで使用するテスト・ケースを選択するときには、以下の点を考慮してください。
    • 優れたテスト・ケースは、アプリケーションでオブジェクトが作成される領域を使用します。ほとんどの場合、アプリケーショ ンの知識が必要になります。シナリオの説明で、新規レコードの追加、HTTP セッションの作成、ト ランザクションの実行、およびレコードの検索などのような、データ・スペースの作成を 推奨している場合があります。
    • オブジェクトのコレクションが使用されている領域を調べてください。通常、メモリー・リークは同じクラス内のオブジェクトから構成されています。また、対応する追加メソッドを呼び出すことによって、オブジェク トへの参照が暗黙的に保管される場所である、vector や hashtable などのコレクション ・クラスも一般的です。例えば、Hashtable オブジェクトのゲット・メソッドは、検索済みのオブジェクトへの参照を除去しません。

ヒープの消費が、ワークロードが高いときにリークが起こった可能性を示している (アプリケーション・サーバーの CPU 使用率が常に 100% 近くなっている) のに、その後、ワークロードが低いかほとんどアイドル状態になったときにはヒープが回復するように見えるのは、ヒープのフラグメント化が起きている兆候です。ヒープのフラグメント化は、JVM がガーベッジ・コレクションのサイクル中にメモリー割り振り要求を満たすために十分な量のオブジェクトを解放することができたとしても、ヒープ内の小さな空きメモリー域を圧縮して、連続した大きなスペースを作成する時間がない場合には、起こる可能性があります。

この他に、ヒープのフラグメント化は、小さなオブジェクト (512 バイト未満) が解放された場合にも起こります。オブジェクトが解放されても、ストレージは回復しません。この結果、ヒープ圧縮が実行されるまでは、メモリーのフラグメント化が進みます。

ヒープのフラグメント化は圧縮を強制するによって削減できますが、これを行う場合パフォーマンス・ペナルティーがあります。 Java -X コマンドを使用して、メモリー・オプションのリストを参照します。

Java ヒープ・パラメーター

Java ヒープ・パラメーターも、ガーベッジ・コレクションの動作に影響します。 ヒープ・サイズを増やすと、より多くのオブジェクトを作成することができます。大きなヒープは満杯になるまでに時間がかかるので、 ガーベッジ・コレクションが実行されるまでにアプリケーションが 稼働する時間が長くなります。 ただし、大きなヒープは圧縮にも時間がかかるので、ガーベッジ・コレクションの所要時間が長くなります。 ヒープ設定についての詳細は、Java 仮想マシンの調整 を参照してください。

Java ヒープ情報は SMF レコードに含まれており、 コンソール・コマンド DISPLAY,JVMHEAP で動的に表示することができます。

パフォーマンス分析のためには、初期ヒープ・サイズと最大ヒープ・ サイズを等しくします

初期ヒープ・サイズ

Java アプリケーションの作業セット・サイズが不明な実動システムを調整する場合は、 初期ヒープ・サイズを、まず、最大ヒープ・サイズの 25% にするとよいでしょう。 これにより、JVM はヒープのサイズをアプリケーションの作業セットのサイズに適合させようとします。



この図は、3 つの CPU プロファイルを示し、 それぞれ固定ワークロードで Java ヒープ設定値を変えながら稼働しています。 中央のプロファイルでは、初期ヒープ・サイズと最大ヒープ・サイズは 128MB に設定されています。ガーベッジ・コレクションは 4 回行われています。ガーベッジ・コレクションの合計時間は、合計実行時間の約 15% です。 ヒープ・パラメーターを倍の 256MB にすると、一番上のプロファイルのように、 ガーベッジ・コレクション間の作業時間の長さが増えていきます。 ガーベッジ・コレクションは 3 回しか行われませんが、それぞれのガーベッジ・コレクションの長さも増大しています。3 番目のプロファイルでは、ヒープ・サイズが 64MB に削減され、逆の結果が示されています。ヒープ・サイズが小さくなると、ガーベッジ・コレクション間の時間と個々のガーベッジ・コレクションの時間は、どちらも短くなります。 これらの 3 つの構成すべてについて、ガーベッジ・コレクションの合計時間 は、約 15% です。 この例は、Java ヒープおよびそれとオブジェクト使用率との関係について重要な概念 を示しています。Java アプリケーションには、 常にガーベッジ・コレクションのコストがかかります。

一連のテスト実験を、Java ヒープ設定値を変えながら実行します。 例えば、128MB、192MB、256MB、および 320MB で実験を行います。 各実験の間、合計メモリー使用量をモニターします。 ヒープをあまり拡張しすぎると、ページングが起こります。 ページングが起こったら、ヒープのサイズを減らすか、またはシステムにメモリーを追加してください。 実行がすべて終了したら、以下の統計値を比較してください。
  • ガーベッジ・コレクションの呼び出し回数
  • ガーベッジ・コレクション 1 回分の呼び出しの平均所要時間
  • ガーベッジ・コレクション 1 回分の呼び出し時間の長さと、 呼び出し間の平均時間間隔の比率。
アプリケーションがオブジェクトを過剰に使用しておらず、 メモリー・リークもない場合は、メモリーの使用状況は定常状態に達しています。ガーベッジ・コレクションが実行される頻度も 少なく、所要時間も短く済みます。

ヒープのフリー・スペースが 85% 以上で安定している場合は、アプリケーション・サーバーおよびアプリケーションがヒープに割り振られたメモリーをあまり使用していないため、ヒープ・サイズの最大値を小さくすることを検討してください。

大規模なセル構成での構成更新のパフォーマンス [バージョン 6.0.2]

大規模なセル構成では、構成更新のパフォーマンスと整合性検査のどちらがより重要かを決定する必要があります。 構成の整合性検査がオンになっている場合は、構成変更の保管または多数のアプリケーションのデプロイに時間がかかることがあります。 必要となる時間に影響する要素は次のとおりです。
  • セル内に定義されたアプリケーション・サーバーまたはクラスターが多ければ多いほど、構成変更の保管にかかる時間が長くなります。
  • セル内にデプロイされたアプリケーションが多ければ多いほど、構成変更の保管にかかる時間が長くなります。
構成変更にかかる時間に問題がある場合は、JVM 設定に config_consistency_check カスタム・プロパティーを追加して、このプロパティーの値を false に設定します。
  1. 管理コンソールで、「システム管理」>「デプロイメント・マネージャー」とクリックします。
  2. 「サーバー・インフラストラクチャー」の下で「Java およびプロセス管理」をクリックし、さらに「プロセス定義」をクリックします。
  3. 「追加プロパティー」の下で、「Java 仮想マシン」>「カスタム・プロパティー」>「新規」とクリックします。
  4. 「名前」フィールドに config_consistency_check を入力し、「値」フィールドに false と入力します。
  5. OK」をクリックしてから「保管」をクリックして、これらの変更をマスター構成に適用します。
  6. サーバーを再始動します。



関連タスク
アプリケーション・サービス提供環境のチューニング
参照トピック    

ご利用条件 | フィードバック

最終更新: Jan 21, 2008 10:52:11 PM EST
http://publib.boulder.ibm.com/infocenter/wasinfo/v6r0/index.jsp?topic=/com.ibm.websphere.zseries.doc/info/zseries/ae/rprf_javamemory.html