2009-06-21 8 views
8

多くのI/Oを必要とする非常に高速なJavaコードを作成しようとしています。私はのByteBufferを返すメモリマップファイルを使用しています:Javaでメモリマップされたファイル

public static ByteBuffer byteBufferForFile(String fname){ 
    FileChannel vectorChannel; 
    ByteBuffer vector; 
    try { 
     vectorChannel = new FileInputStream(fname).getChannel(); 
    } catch (FileNotFoundException e1) { 
     e1.printStackTrace(); 
     return null; 
    } 
    try { 
     vector = vectorChannel.map(MapMode.READ_ONLY,0,vectorChannel.size()); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     return null; 
    } 
    return vector; 
} 

私が抱えている問題は、(バイト[]配列を返さなければならない)のByteBufferの.ARRAY()メソッドが動作しないということです読み取り専用ファイルの場合メモリに構築されたメモリバッファとディスクから読み込まれたバッファの両方で動作するように自分のコードを書きたいと思います。しかし、私はByteBuffer.wrap()関数を使って、すべてのバッファをラップしたくないのですが、これは処理が遅くなることを心配しています。だから私はすべての2つのバージョンを書いています。一つはバイト[]をとり、もう一つはByteBufferをとります。

すべてをラッピングする必要がありますか?または、私はすべてをダブルライトする必要がありますか?

+3

ベンチマークを行い、結果を投稿してください。たとえ専門家があなたの状況に適していない方向を指すことができます。基準!!!! – basszero

答えて

10

ByteBuffersが最初に.array()を呼び出すメモリマッピングサポートによって作成されたかどうかは、実際にチェックしましたか?readonly/readwriteに関係なくですか?

私が知る限り、答えはです。です。直接byte[]アレイをByteBuffer.array()経由で返すByteBufferの能力はByteBuffer.hbbyte[])の存在によって決定されます。これはMappedByteBufferが作成されると常にnullに設定されます。

質問者がやりたいことと似たようなことをしたいと思っていたので、私はちょっと嫌です。

+0

私は同意します。それは吸う。 ByteBufferがarray()を実装していないとは思えません。 一方、私たちはいくつかのパフォーマンステストを行いました。プログラムマッピングを使用するよりもメモリマップファイルで.get()を使用する方が時間がかかることがあり、プログラムioを使用する方が速いことがあります。それは非常に奇妙です。しかし、メモリマップされたファイルよりもプログラムされたioの方がずっと多くなっています。 – vy32

+3

'byte []'はヒープ上になければなりません。メモリにマップされたメモリブロックは、ヒープの外側になければなりません。区別が透明であればいいでしょうが、私はByteBufferのgetLong/putLongメソッドを使用する方が好きです(これらはネイティブの順序付けを使用する方がはるかに高速です) –

1

ByteBuffer.wrap()機能を使用しても負担がかかりません。これは単純なオブジェクトを割り当て、いくつかの整数を初期化します。したがって、ByteBufferに対してアルゴリズムを書くことは、読み取り専用ファイルで作業する必要がある場合には最善の策です。

4

ラッピングバイト[]は処理を遅らせることはありません。巨大な配列コピーやその他の小さなパフォーマンス悪はありません。 JavaDocsより:java.nio.ByteBuffer .wrap()

バイト配列をバッファにラップします。

新しいバッファは、指定されたバイト配列によってバッキングされます。つまり、 バッファを変更すると、 の配列が変更され、その逆の結果になります。 新しいバッファの容量と の制限はarray.lengthになり、その の位置はゼロになり、そのマーク は未定義になります。そのバッキング配列 は指定された配列になり、配列 のオフセットはゼロになります。

+0

ありがとうございます。 .get(i)はメソッド呼び出しを伴い、[i]はバイトコードで行われるので、私はちょうど[i]の代わりに.get(i)を使ってすべてのバイトを読むことを心配しています。 – vy32

+4

これは非常に「きめ細かい」パフォーマンス上の問題のように思えますし、時期尚早の最適化のような匂いがします。 JVMはこのようなものについては良いです。ベンチマークして、それを自分自身に証明してください。 –

+0

実際、テラバイトの情報を処理するコンピュータフォレンジックをやっています。これまでの私の経験では、JVMは私が望むほど最適化していませんでした。 – vy32

5

いつも車輪を再発明しないこと。 ApacheはI/O操作を実行するための美しいライブラリを提供しています。見てみるhttp://commons.apache.org/io/description.html

ここではそのシナリオを示します。 が記憶しているデータがあるとしますが、あらかじめデータの量がどれくらいあるかわからないとします。 あまりにも多い場合は、メモリを奪う代わりにディスク に書き込むが、ディスクが遅く、 のクリーンアップのための追跡が必要なリソースであるため、 が必要になるまでディスクに書きたくない。

したがって、一時バッファを作成し、それに書き込みを開始します。 がメモリに保持したい値のしきい値に達した場合は、 ファイルを作成し、そのファイルにバッファ内の内容を書き出し、バッファの代わりにすべての の後続データをファイルに書き込む必要があります。

それは何ですかDeferredOutputStreamあなたのためです。それはスイッチオーバーの時点で回ってすべての厄介なものを隠す。 最初に 遅延ストリームを作成し、しきい値を設定してから だけ心のコンテンツに書き留めてください。

編集:ちょうどgoogleを使用して小さな再検索を行いましたが、このリンクが見つかりました: http://lists.apple.com/archives/java-dev/2004/Apr/msg00086.html (ライトニングファーストファイルの読み書き)非常に印象的。

+0

私が間違っている場合は、私を修正してください。あなたはI/O操作を行うための速い方法を探しています。正しい?? –

+0

実際、私は私がやっている速い方法を探しているだけですが、バッファコピーを最小限に抑えてバッファを処理する方法も探しています。 – vy32

+0

@ GauravSaini:Apache Commons-ioから 'DeferredOutputStream'を参照していますか?私はv2.3とv2.2のJavadocでそのようなクラスを見つけることができません。 –

関連する問題