2012-03-29 10 views
2

私はいくつかのグラフライブラリを学習し、テストしています。奇妙な問題にぶち当たっています(グラフに固有のものではありませんが、これは一般的なJava関連です)。私は 'java.lang.OutOfMemoryError:GCオーバーヘッドの上限を超えています'というメッセージを表示しています。 I understand this error means that garbage collecting spending most of the cpu time and not returning any memoryしかし、私はこれを回避する方法がわかりません。JVMに使用可能なメモリがたくさんある場合、なぜ 'java.lang.OutOfMemoryError:GCオーバーヘッドの上限を超えました'が表示されますか?

基本的に私は(学習目的のために)、メモリ内に多数のグラフノードを作成するのに必要な時間を見たいと思っています。私のシステムはセントを実行しており、私は7ギガのRAMを持っていますが、プログラムは25%を超えることはありません(私は 'トップ'経由で見ることができます) .jar -Xmx7g -XX:+ UseConcMarkSweepGC -XX:-UseGCOverheadLimit '(jungtester.jarは私のプログラムです)。使用可能なメモリをすべて使用していないようだが、およそ350万のノードの後で死んでいる。これはちょうどforループなので奇妙だ。だから、メモリがいっぱいになるまでノードを追加するだけだと思った。

私はJVMの内部の仕組みにはかなり新しいので、これをどのように過去のものにするかの提案はすばらしくなるでしょう。

それが助け場合は、ここではコードです:

import edu.uci.ics.jung.graph.DirectedGraph; 
import edu.uci.ics.jung.graph.DirectedSparseGraph; 

public class main { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     // TODO Auto-generated method stub 
     System.out.println("starting..."); 
     long startTime = System.currentTimeMillis(); 
     DirectedGraph<Integer,Integer> graph = new DirectedSparseGraph<Integer, Integer>();; 
     graph.addVertex(1); 
     graph.addVertex(2); 
     graph.addEdge(1, 1,2); 

     for (int i = 0; i < 1000000; i++) { 
      graph.addVertex(i); 
      //System.out.println(i + " means we are " + (float) i/1000000 + "% done."); 
     } 
     long endTime1 = System.currentTimeMillis(); 
     System.out.println("done adding 1000000 in " + (endTime1 - startTime)); 


     for (int i = 1000001; i < 10000000; i++) { 
      graph.addVertex(i); 
      graph.addEdge(i, i, i-1000000); 
      System.out.println(i + " means we are " + (float) i/1000000000 + "% done."); 
     } 

     long endTime = System.currentTimeMillis(); 

     System.out.println("It took " + (endTime - startTime)); 
    } 

} 

UPDATE:私はそれが動作するようになったが、私はなぜわからないが、順序が重要。私の上のコマンドは、私が置いた後に何も取らなかった - 瓶、しかし私は最後に - 瓶を追加したときに動作するようです。

+1

アプリケーションの実行中にJVMを監視するためにjconsole(使用可能なXがある場合)を使用すると、何が起きているかが表示されます。 Topは、jconsoleのようにJVMのリアルタイム統計を表示するほど細かくはありません。 – robertvoliva

+1

これは32ビットまたは64ビットマシンで実行していますか? 32ビットシステムでは、7GのRAMは使用できません。 –

+2

@PéterTörök - そうですが、32ビットマシンで '-Xmx7g'を使用すると、JVMは起動しません。だから私はこれが問題だとは思わない。 –

答えて

1

私は何をここで起こっていることは、あなたのプログラムの性質の不幸な結果であり、あなたが

を選択したGCの設定は基本的に、あなたのプログラムは非常に迅速にノードの膨大な数を作成している、と(ルックスであることを考えますそのようなものは決して実行の終わりまでそれらのいずれかを解放することはありません)。したがって、GCが実行されるたびに、作業中の "From"スペース内のすべてのオブジェクトをトレースして避難させる必要があります。この作業は、空間内のオブジェクトの数に比例します。アプリケーションが進むにつれて、スペースが大きくなり、オブジェクトの数が増え続け、GCがオブジェクトを動かす時間がますます大きくなります。これは、スループットコレクタよりも大きなオーバーヘッドを持つCMSコレクタを実行しているために悪化する可能性があります。

これは、利用可能なメモリの25%しか使用していないように見える理由を説明します。しかし、あなたがtopから得ている数字が誤解を招く可能性もあります。私はあなたがjconsoleなどから得た数字を信じる方がより意欲的です。

また、GCロギングをオンにして、奇妙なことが起こっているかどうかを確認します。たとえば、アプリケーションの動作がCMSコレクタを圧倒し、JVMが世界的なGCに切り替わる可能性があります。 (私は漠然とこの問題が発生したときに、大きなパフォーマンスヒットを取ることを聞いて思い出し、それはGCオーバーヘッドの制限をヒットするJVMを引き起こすのに十分である可能性があります。)


ですから、の挙動を改善するために何ができますかこのアプリケーションを実行しているJVM

  • CMSの代わりにスループットコレクタを使用してみてください。
  • 可能なJVMをお持ちの場合は、新しいG1コレクタを使用してみてください。
  • 初期ヒープサイズも7ギガバイトに設定してください。-Xms7gを使用してください。

GCログを慎重に分析すると、他のことを試してみることができます。

おそらく、あなたがすることができる最もよいことは、これを捨てることです(私が望む)非現実的なベンチマークです。

+0

あなたは正しいかもしれません。私が気づいたのは、最小トップ25%のメモリ使用量で25%のメモリ使用量に達した後、1分後にエラーが発生するということでした。私はロギングを行う方法を研究し、CMSコレクタなしで試してみます(リンクされた質問で、より多くのメモリを使用できる可能性があるので読みました) –

1

私は決して専門家ではありませんが、これは私の推測です。

それがメモリから完全になるまで、それはGCしないだろう場合は、それだろう...

A)...)、メモリ

Bの非常に大/不必要に大量に消費します。 ..実際にはにはGCを実行するのにがあった頃、パフォーマンスに大きな影響を与えます。

はGCがメモリ不足になる前に実行されます。このGCプロセスは、作成中の数百万のノードに追いつけず、恐らく深いオブジェクトグラフに投げ込めません。

+0

-XX:-UseGCOverheadLimitはGCをまったく実行しないように指示しますか?私はリンクされた質問で、問題がチェックされないようにすると書いていました。また、あなたはもう少し質問をしました。何かが大きすぎるとか不必要に何かを判断するのはどうですか?それは私が他のどこかでデータを使用することができることを知っているすべてのために?これを止める方法はありますか?私はちょうどJVMが正しいことをやっているバックグラウンドタスクを混乱させています。 –

+0

'-UseGCOverheadLimit'の良い点です。私は良い答えがありません。あなたのフォローアップの質問について:これらのことは '-XX'オプションを使って微調整することもできます。たとえば、 '-XX:MaxHeapFreeRatio = 70'([source](http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html))があります。 – aioobe

関連する問題