2

私のJavaアプリケーションは、メモリマップトファイル(MappedByteBuffer、FileChannel、RandomAccessFile)を使用して大きなバイナリデータファイルを処理します。多くの場合、バイナリファイルを拡張する必要があります。現在のアプローチは、ファイルをより大きな領域に再マップすることです。

それは動作しますが、2つの問題があります

  1. ファイルが大きくなるにつれて、成長にはますます時間がかかります。
  2. グローが非常に高速に実行される場合(たとえば、while(true)ループ内)、再マップ操作が約30,000回以上実行された後、JVMは永久にハングします。

代替アプローチは何ですか、そしてこれを行うための最良の方法は何ですか?

また、なぜ2番目の問題が発生するのか理解できません。その問題についてのあなたの意見も提案してください。

ありがとうございました!

それが役立つ場合、ファイルを成長させるための現在のコード:

(set! data (.map ^FileChannel data-fc FileChannel$MapMode/READ_WRITE
                         0 (+ (.limit ^MappedByteBuffer data) (+ DOC-HDR room))))
4

3 に答える 3

5

おそらく、ファイルをより大きなチャンクに拡大したいと思うでしょう。動的配列のように、再マップするたびに倍増を使用して、成長のコストが償却定数になるようにします。

なぜリマップが30,000回後にハングするのかわかりませんが、それは奇妙に思えます。しかし、私が提案するスキームを使用すれば、30,000回未満のリマップで逃げることができるはずです。

于 2012-09-14T06:44:41.393 に答える
0

クリーナーを明示的に呼び出しても、JVMはメモリマッピングをクリーンアップしません。訂正ありがとうございます@EJP。

これらを32,000個作成すると、それらはすべて一度に存在する可能性があります。ところで:15ビットの制限に達しているのではないかと思います。

これに対する唯一の解決策は次のとおりです。それほど多くのマッピングを作成しないでください。4K未満のマッピングでディスク全体を4TBディスクにマッピングできます。

使用量が増えることがわかっている場合は、16〜128 MB未満のマッピングを作成せず、マッピングごとに最大1GBを検討します。わずかなコストでこれを実行できる理由は、実際にページを使用するまでメインメモリとディスクスペースが割り当てられないためです。つまり、メインメモリの使用量は一度に4KB増加します。

2 GBのマッピングを作成しない唯一の理由は、Integer.MAX_VALUEのサイズ制限のためにJavaがこれをサポートしていないことです:( 2 GB以上の場合は、複数のマッピングを作成する必要があります。

于 2012-09-14T07:14:26.413 に答える
0

倍増やその他の定数乗数のようにファイルを指数関数的に増大させる余裕がない限り、MappedByteBufferそれらの制限(ファイルを増大できない、GCがないなど)を考慮して、本当に必要かどうかを検討する必要があります。私は個人的に問題を確認するかRandomAccessFile、「rw」モードを使用して、おそらくその上に仮想アレイレイヤーを配置します。

于 2012-09-14T10:16:18.827 に答える