26

ここに画像の説明を入力してください

VisualVMのスクリーンショットは、IOを多用するJVMプログラム(Scalaで記述)を実行したときに撮影されました。ヒープサイズは4 GBで、使用中は2GBのみでした。JVMプログラムは、メモリマップトファイルを使用します。

「マップされたバッファプール」と「直接バッファプール」とはどういう意味ですか?

それらのプールは非常にいっぱいのようです。JVMプログラムはメモリマップトファイルを使用するため、プールが大きい場合、パフォーマンスが向上しますか?もしそうなら、それらのサイズを増やす方法は?

マップされたすべてのファイルのサイズは約1.1GBです。

4

1 に答える 1

66

ダイレクトバッファ

ダイレクトバッファは、JavaをOS I / Oサブシステムにインターフェイスするために通常使用されるメモリのチャンクです。たとえば、OSがソケットまたはディスクからデータを受信するときにデータを書き込み、Javaが直接読み取ることができる場所として使用されます。

OSとバッファを共有することは、OSからJavaのメモリモデルにデータをコピーする元のアプローチよりもはるかに効率的です。これにより、データはガベージコレクションの対象となり、edenから移行する際のデータの再コピーなどの非効率になります- >サバイバー->テニュア->パーマネント世代へ。

スクリーンショットでは、16KBの直接バッファーのバッファーが1つだけあります。Javaは必要に応じてこのプールを拡張するため、青い領域がブロックの上部にあるという事実は、これまでに割り当てられたすべてのバッファメモリが使用中であるという単なるステートメントです。これは問題ではないと思います。

マップされたバッファプール

マップされたバッファプールは、JavaがFileChannelインスタンスに使用するすべてのメモリです。

各FileChannelインスタンスには、OSと共有されるバッファーがあります(すべての効率上の利点を備えた直接バッファーと同様です)。メモリは基本的に、ファイルの一部へのRAM内ウィンドウです。モード(読み取り、書き込み、またはその両方)に応じて、Javaはファイルの内容を直接読み取りおよび/または変更でき、OSは変更されたデータをディスクに直接供給またはフラッシュできます。

このアプローチの追加の利点は、OSがシャットダウンしているときなど、OSが適切と判断したときに、このバッファーをディスクに直接フラッシュできることと、OSがコンピューター上の他のプロセスからファイルのその部分をロックできることです。

スクリーンショットは、12個のFileChannelオブジェクトで約680MBが使用されていることを示しています。繰り返しになりますが、Javaは成長し​​ます。これはScalaがより多くを必要とするためです(そしてJVMはOSから追加のメモリを取得できます)。したがって、680MBがすべて使用されているという事実は重要ではありません。それらのサイズを考えると、プログラムはこれらのバッファを効果的に使用するようにすでに最適化されているように思われます。

マップされたバッファプールのサイズを増やす

Javaは、ガベージコレクションスペースの外部にFileChannelバッファ用のメモリを割り当てます。-Xmxこれは、ここでは重要ではないなどの通常のヒープサイズパラメータを意味します

FileChannelのバッファのサイズは、mapメソッドで設定されます。これを変更すると、Scalaプログラムを変更する必要があります

バッファが10〜100 KBのオーダーのしきい値サイズに達すると、FileChannelバッファサイズを増やすと、パフォーマンスが向上する場合と向上しない場合があります。これは、プログラムがバッファをどのように使用するかによって異なります。

  • いいえ:ファイルが端から端まで正確に1回読み取られる場合:ほとんどの場合、ディスクまたは処理アルゴリズムを待機しています。
  • たぶん:ただし、アルゴリズムがファイルの再訪問部分を何度もスキャンする場合は、サイズを大きくするとパフォーマンス が向上する可能性があります。
    • ファイルを変更または書き込む場合、バッファーが大きいほど、より多くの書き込みを1つのフラッシュに統合できます。
    • ファイルを読み取る場合、オペレーティングシステムはすでにファイル(ディスクキャッシュ)をキャッシュしている可能性が高いため、ゲインはわずかである可能性があります。JVMのサイズを逆に増やすと、有効なディスクキャッシュサイズが縮小されてパフォーマンスが低下する可能性があります
    • いずれの場合も、アプリケーションは、たとえば独自の論理レコードポインタをキャッシュに実装するなどして、メリットを得るように特別にコーディングする必要があります。

アプリケーションのプロファイリングを試して、I / O待機を探します(JprofilerとYourKitはこれに優れています)。ファイルI/Oは実際には問題ではない可能性があります-時期尚早の最適化の犠牲にならないでください。I / O待機が合計経過時間のかなりの部分を占める場合は、より大きなバッファーサイズを試す価値があるかもしれません。

さらに詳しい情報

https://blogs.oracle.com/alanb/entry/monitoring_direct_buffers

また、FileChannelがメモリの解放に適していないというバグがJVMで報告されていることにも注意してください。java.nio.MappedByteBufferを使用する場合のOutOfMemoryの防止で詳しく説明されています

于 2013-04-02T03:45:14.953 に答える