web-dev-qa-db-ja.com

JavaアプリケーションのCPU使用率が高い-なぜ?

Javaアプリケーション(Webベース)があり、数時間にわたって非常に高いCPU使用率(ほぼ90%)を示すことがあります。LinuxTOPコマンドはこれを示します。 、問題はなくなります。

調査するために

スレッドダンプを使用して、スレッドが何をしているかを見つけます。いくつかのスレッドは'RUNNABLE'状態で見つかり、いくつかは他のいくつかの状態で見つかります。繰り返されるスレッドダンプを取得すると、'RUNNABLE'状態で常に存在するスレッドがいくつか表示されます。だから、彼らは犯人のようです。

しかし、どのスレッドがCPUを占有しているのか、無限ループに入っているのか(それによってCPU使用率が高くなる)を確実に判断することはできません。

問題のあるコードは何もログに記録していない可能性があるため、ログは必ずしも役に立ちません。

調査方法-アプリケーションまたはwhat-threadのどの部分が高いCPU使用率を引き起こしていますか?-その他のアイデアはありますか?

35
Jasper

プロファイラーがセットアップに適用できない場合は、 この投稿 の手順に従ってスレッドを識別しようとする場合があります。

基本的に、3つのステップがあります。

  1. 実行top -HおよびCPUが最も高いスレッドのPIDを取得します。
  2. pIDを16進数に変換します。
  3. スレッドダンプでHEX PIDが一致するスレッドを探します。
40
ericson

ガベージコレクションの問題の犠牲になる可能性があります。

アプリケーションがメモリを必要とし、ガベージコレクターを使用するように構成されているものが少なくなると、多くのCPUサイクルを消費するガベージコレクターが頻繁に実行されます。何も収集できない場合、メモリは少なくなり、繰り返し実行されます。アプリケーションを再デプロイすると、メモリがクリアされ、ガベージコレクションが必要以上に発生しないため、CPU使用率は再びいっぱいになるまで低くなります。

アプリケーションにメモリリークの可能性がなく、メモリ用に適切に構成されていることを確認する必要があります(-Xmxパラメータ、 Javaオプション-Xmxの略称 )とは)

また、Webフレームワークとして何を使用していますか? JSFはセッションに大きく依存し、多くのメモリを消費します。ステートレスであることを考慮してください。

12
Alexandre Jacob

これらのピークCPU時間の間、ユーザーの負荷はどの程度ですか?これはWebベースのアプリケーションだと言うので、思い浮かぶのはメモリ使用率の問題です。たとえば、セッションに多くのものを保存し、セッションカウントが十分に高くなると、アプリサーバーはスラッシングを開始します。これは、使用しているスキームによってはGCが問題を悪化させる場合もあります。アプリとサーバー構成に関する詳細情報は、より多くのデバッグのアイデアを示すのに役立ちます。

2
WPrecht

スレッドダンプでは、次のように行番号を見つけることができます。

現在実行中のメインスレッド用...

"main" #1 prio=5 os_prio=0 tid=0x0000000002120800 nid=0x13f4 runnable [0x0000000001d9f000]
   Java.lang.Thread.State: **RUNNABLE**
    at Java.io.FileOutputStream.writeBytes(Native Method)
    at Java.io.FileOutputStream.write(FileOutputStream.Java:313)
    at com.rana.samples.**HighCPUUtilization.main(HighCPUUtilization.Java:17)**
1
ranafeb14

最初のアプローチは、 Thread.sleep へのすべての参照を見つけて、それを確認することです。

  1. 睡眠は正しいことです-可能であれば、何らかの種類の待機メカニズムを使用する必要があります-おそらくBlockingQueueを慎重に使用すると役立つでしょう。

  2. 睡眠が正しいことである場合、あなたは正しい時間眠っていますか?これはしばしば答えるのが非常に難しい質問です。

マルチスレッド設計で最もよくある間違いは、何かが起こるのを待つときにやらなければならないことは、それを確認し、短いループでしばらく寝ることだけだと信じることです。これが効果的な解決策となることはめったにありません。発生する場合は常にwaitを試みる必要があります。

2番目に一般的な問題は、スリープせずにループすることです。これはさらに悪く、追跡するのが少し簡単です。

1
OldCurmudgeon

質問に「linux」を割り当てませんでしたが、「Linux top」に言及しました。したがって、これは役に立つかもしれません:

小さなLinuxツールthreadcpuを使用して、スレッドを使用しているほとんどのCPUを特定します。 jstackを呼び出してスレッド名を取得します。また、パイプの「sort -n」を使用すると、CPUの使用順に並べられたスレッドのリストを取得できます。

詳細はこちらをご覧ください: http://www.tuxad.com/blog/archives/2018/10/01/threadcpu_-_show_cpu_usage_of_threads/index.html

さらに詳細が必要な場合は、スレッドダンプを作成するか、スレッドでstraceを実行します。

0
reichhart