2

現在、4D の球/平面上の巨大なベクトル フィールド (> 250'000) を視覚化するアプリケーションを開発しています。プロセスを高速化するために、頂点、法線、および色に VBO を使用しています。GPU に送信する前にデータを準備するために、バッファ (FloatBuffer、ByteBuffer など) を使用しています。

シリンダーへのデータ: 各シリンダーは 16 * 9 + 16 * 3 = 192 float -> 192 * 4 バイト = 768 バイトを使用します。

頂点を送信した後、次のクリーンアップを行っています。

// clear all buffers
vertexBufferShell.clear();
indexBufferShell.clear();

vertexBufferShell = null;
indexBufferShell = null;

JConsole で監視したところ、GarbageCollector が「正しく」実行されていないことがわかりました。シリンダ数を減らしても、メモリは解放されません。JConsole Monitoring Tool には、GC を実行するためのボタンがあり、手動で行うとメモリが解放されます (大量のシリンダーをロードして大幅に減らすと、GC によって 600MB 以上がクリーンアップされることがあります)。

JConsole のイメージは次のとおりです。 JConsole 出力、[GC の実行] ボタンを押した後にメモリがクリーンアップされる

問題は、コード内でこのバッファを自分でクリーンアップするにはどうすればよいかということです。clear メソッドを呼び出して参照を null に設定するだけでは不十分です。System.gc()の呼び出しも試みましたが、効果はありませんでした。何か考えはありますか?

4

4 に答える 4

3

メモリ使用量が増加する理由はいくつもあります。この操作を実行するたびにメモリが増加しない限り、メモリリークではないと思います。初めて発生する場合は、このライブラリをロードするためにメモリが必要な可能性があります。

メモリの増加がどこにあるかを確認するために、ヒープ ダンプを取得するか、少なくともjmap -histo:liveその前後に取得することをお勧めします。

VisualVM や YourKit などのメモリ プロファイラーを使用すると、メモリが保持されている場所と理由が表示されます。

于 2011-08-12T10:09:08.373 に答える
1

gcがそれをクリーンアップできれば、実際にはメモリリークではありません。メモリの浪費かもしれませんが、アプリは800MBを超えるヒープを使用できるように構成されているようです。これは、ガベージコレクションのパフォーマンスとメモリ使用量の間のトレードオフです。また、より小さなヒープサイズでアプリケーションを実行することもできます。

于 2011-08-12T14:09:23.077 に答える
1

メモリリークは発生しない可能性がありますが、オブジェクトはTernured(マイナーgcで生きたまま通過したオブジェクトが移動する領域)に移動します。

あなたが見るこれらの大きなステップは、Young Edenそれがいっぱいで、マイナーなgcが生きているオブジェクトをに移動した後 かもしれませんTernure

ガベージコレクターとメモリの調整を試みることもできます。

TernuredフルGCでリリースするために絶えず渡されているミドルレングスのライブオブジェクトがたくさんあるかもしれません。それらの寸法を適切に設定すると、それらのオブジェクトはマイナーgcになります。

これを行うためのjvm引数はたくさんあります。

見るのに良い場所はここです。

これはあなたに適しています:

-XX:NewSize=2.125m 
Default size of new generation (in bytes) 
[5.0 and newer: 64 bit VMs are scaled 30% larger; x86: 1m; x86, 5.0 and older: 640k]

よろしく。

于 2011-08-12T13:59:32.847 に答える
1

JVM は、必要になるまでオブジェクトを解放しません (例: Xmx に達する)。これは、現在の JVM で見られるすべての GC の背後にある主要な概念の 1 つです。それらはすべて、同時実行であっても、スループットに対して最適化されています。GC グラフに異常は見られません。

完全な GC の後に使用されるヒープが時間の経過とともに絶えず増加する場合は、リークになります。そうでない場合は、すべて問題ありません。

要するに: foo=null; オブジェクトは解放せず、参照のみを解放します。GC はいつでもメモリを解放できます。

また、 buffer.clear() はバッファをクリアせず、pos=0 と limit=capacity を設定します - 以上です。詳細については、javadoc を参照してください。

ビジュアルVM +1

楽しんで :)

(オフトピック: バッファーが大きくて静的な場合は、permgen に割り当てる必要があります。Buffers.newDirectFloatBuffer() は、最新の gluegen-rt のユーティリティ メソッドの 1 つです)

于 2011-08-12T22:40:32.163 に答える