2011-07-26 4 views
4

これらのことは、徹底的に分析して良い提案をするには、明らかに検査とコードの入手が必要です。それにもかかわらず、それは常に可能ではありません、私は以下の情報に基づいて良いヒントを私に提供することが可能であることを願っています。Javaメモリ使用量/スレッドプールパフォーマンスの問題

リスナースレッドを使用して着信データを受信するサーバーアプリケーションがあります。入力データはアプリケーション固有のメッセージに解釈され、これらのメッセージはイベントを発生させます。

これまでのところ、私は物事がどのように行われているかについて何の支配もしていません。

これは従来のアプリケーションであるため、これらのイベントは以前は同じリスナースレッド(主にシングルスレッドアプリケーション)によって処理されていました。イベントはブラックボックスに送られ、結果はディスクに書き出されます。

スループットを向上させるために、スレッドプールを使用してイベントを処理したいと考えました。イベントが作成され、スレッドがブラックボックス呼び出しを処理するたびに、リスナースレッドが新しいタスクを生成できるという考えがあります。最後に、ディスクへの書き込みを実行するバックグラウンドスレッドがあります。

以前のセットアップとバックグラウンドライターだけで、すべて正常に動作し、スループットは従来の1.6倍になりました。

スレッドプールを追加するとパフォーマンスは低下します。最初はすべてがスムーズに動くようですが、しばらくするとすべてが非常に遅くなり、最終的に私はOutOfMemoryExceptionsを取得します。変わったことは、タスクがプールに追加されるたびにアクティブなスレッドの数を表示すると(キューに登録されているタスクの数などの情報とともに)、スレッドプールに問題がないかのように見えるということですプロデューサ(リスナスレッド)。

先頭へ-Hを使用してCPU使用率をチェックすると、最初は非常に均等に広がっていますが、最後にワーカースレッドはほとんどアクティブでなく、リスナースレッドだけがアクティブです。しかし、それ以上のタスクを提出するようではありません...

誰もこれらの症状の理由を仮定することはできますか?複数のスレッドが追加されたときにうまくいかない、レガシーコードに何かがある(私が制御できない)可能性が高いと思いますか?メモリ不足の問題は、どこかのキューが大きくなりすぎるためですが、スレッドプールにはキューに入れられたタスクがほとんど含まれていないので、それはできません。

アイデアを歓迎します。このような状況をより効率的に診断する方法のアイデアが特にあります。私のスレッドが何をしているのかについて、より良いプロファイルを得るにはどうすればいいですか?

ありがとう。

+0

ブラックボックスは端末コンポーネントですか、接続されていますか?それはパッシブまたはアクティブなコンポーネントですか?あなたのスレッドプールはどこにありますか? – alphazero

+0

ブラックボックスの詳細を教えてください。 – toto2

+0

blackboxは、タイプAのオブジェクトを受け取り、さまざまな操作を実行してタイプBのオブジェクトを生成する内部関数です。これは、アプリケーションの計算部分であり、プール内のスレッドが実行するものです。スレッドプールは標準のoracle/sun jdk実装です。 – UmaN

答えて

4

ありがとうございました。私はJava VisualVMを読み、これをツールとして使用しました。結果と結論は以下に詳述されている。うまくいけば、写真は十分に長く働くはずです。

私は最初にプログラムを実行し、いくつかのヒープダンプを作成しました。私はダンプを解析して、すべてのメモリを占有しているかどうかを考えました。ダンプファイルが非常に大きく、ワークステーションにアクセスしようとすると限界があります。 1回の操作のために2時間待って、私はこれをすることができないことに気付きました。

私の次の選択肢は何か私は、愚かには十分考えていなかった。アプリケーションに送信されるメッセージの数を減らすだけで、メモリ使用量の増加傾向はまだそこにあるはずです。また、ダンプファイルは小さくなり、解析が速くなります。

低速でメッセージを送信すると、メモリ不足の問題は発生しませんでした。以下に、メモリ使用量のグラフを示します。

slow send http://img197.imageshack.us/img197/1628/slowsend.png

ピークは累積メモリ割り当ての結果、ガベージコレクタが実行された後である従うトラフあります。メモリ使用量は確かに非常に驚くべきものですが、そこにはおそらく問題がありますが、メモリリークの長期的傾向は見られません。

私は、1秒間に送信されるメッセージの速度を徐々に上げて、アプリケーションが壁に当たる場所を確認し始めました。下の画像は、前の画像とは非常に異なるシナリオを示しています...

fast send http://img200.imageshack.us/img200/151/fastsend.png

送信されたメッセージの割合が増加しているとき、この問題が発生したので、私の推測では、私は非常に迅速に大量のメッセージを受け入れることができるということでリスナースレッドの結果を解放していることであり、これは、より多くの原因割り当て。ガベージコレクタは実行されず、メモリ使用量は壁に当たっています。

もちろん、この問題はさらに深刻ですが、今日私が見つけたことを考えれば、ここからどこに行くのかについてかなり良い考えがあります。もちろん、追加の提案/コメントは歓迎します。

この質問はおそらく、スレッドプールではなくメモリ使用を扱うものとして再分類されるべきです...スレッドプールはまったく問題ではありませんでした。

+0

+1そのような詳細なフォローアップのグラフと! – RHSeeger

5

メモリが不足してメモリが不足していると、メモリリークが発生します。

私はいくつかのJavaメモリアナライザツールを使用して、リークがあるかどうか、およびリークされているものを特定します。時にはあなたは幸運になり、漏れた物はよく知られているので、誰がそれをしてはならないものにぶら下がっているのかがはっきりと分かります。

1

djnaで述べたように、メモリリークの可能性があります。私の推測では、あなたの周りのどこかに、要求への参照を保持していることを次のようになります。ですブラックボックスで要求

  • を扱うスレッドで要求
  • をキューイングのDispatcherスレッドで

    • 要求を処理する
    • ディスクに書き込む書き込みスレッドです。

    あなたがミックスにスレッドプールを追加する前に、すべての作品が見つけたので、私の推測では、プール内のスレッドは、どこかの要求への参照を維持しているということでしょう。つまり、スレッドプールがなければ、スレッドを再利用して情報が消えてしまうということです。

    djnaで推奨されているように、Javaメモリアナライザを使用すると、データのスタック位置を把握できます。

  • 2

    @djnaに同意します。 Java同時実行パッケージのスレッドプールが動作します。スレッドが必要ない場合はスレッドを作成しません。その数のスレッドが期待通りに表示されます。つまり、レガシーコードの何かがマルチスレッドの準備ができていない可能性があります。たとえば、一部のコードフラグメントは同期されません。その結果、一部の要素はコレクションから削除されません。または、いくつかの追加要素がコレクションに格納されます。だから、メモリ使用量が増えています。

    私は今、アプリケーションのどの部分がスレッドプールを使用しているのか正確には分かりませんでした。あなたはイベントを処理するスレッドを1つ持っていましたが、今はこれを行ういくつかのスレッドがありますか?おそらく、スレッド間通信メカニズムを変更しましたか?キューを追加しましたか?これはあなたの調査のもう一つの方向性であるかもしれません。

    幸運を祈る!