2

これは、特に読み取り/書き込みバッファリングされた FileChannel の場合、簡単ではないように見えます。実装のベースとなるオープンソースが実装されているものはありますか?


理解していない人のために明確にするために:

FileChannel は OS レベルでバッファリングを行いますが、Java レベルでバッファリングを行いたいと考えています。ここを読んで理解してください: FileChannel#force とバッファリング


@Peter高速メッセージストリームから巨大なファイルをディスクに書き込みたい。バッファリングとバッチ処理が最適です。したがって、Java でバッチ処理を行い、FileChannel.write を呼び出します。

4

3 に答える 3

5

BufferedOutputStreamラッピングの使用をお勧めしFileOutputStreamます。andをいじってパフォーマンスが向上するとは思えません。また、その方法を使用すると、保守が困難なコードが多数残ることになります。ByteBufferFileChannel

理由は非常に単純です。どのアプローチを採用しても、必要な手順は同じです。

  1. バイトを生成します。これをどのように行う予定なのかは述べていません。これにより、追加レベルの一時的なバッファリングが方程式に導入される可能性があります。ただし、Java データはバイトに変換する必要があります。
  2. バイトをバッファに蓄積します。データを書き込む前にバッファリングして、大量の小さな書き込みを行わないようにする必要があります。それは当然です。しかし、そのバッファーが存在する場所は重要ではありません。
  3. JNI バリアを越えて、バイトを Java ヒープから C ヒープに移動します。ファイルの書き込みはネイティブ操作であり、Java ヒープから直接読み取ることはありません。したがって、Java ヒープにバッファリングしてから、バッファリングされたバイトを移動するか、ダイレクトにバッファリングするかに関係ByteBufferなく (そうです、ダイレクトバッファが必要です)、依然としてバイトを移動しています。を使用してより多くの JNI 呼び出しを行うことになりますが、それByteBufferは限界費用です。
  4. Invokefwriteは、C ヒープからカーネルが保持するディスク バッファーにバイトをコピーするカーネル呼び出しです。
  5. カーネル バッファをディスクに書き込みます。ディスクは低速であるため、これは他のすべての手順を組み合わせたものよりも重要です。

これらの手順をどのように実装するかによって、数マイクロ秒の増減が生じる場合がありますが、基本的な手順を変更することはできません。

は、ステップ #5 が実際に行われるようにするために、FileChannelを呼び出すオプションを提供します。基になる呼び出しはバイトが書き込まれるまで返されないため、force()これは実際には全体的なパフォーマンスを低下させる可能性があります。fsync本当にやりたい場合は、基になるストリームからいつでもチャネルを取得できます。

結論: あなたが実際に IO バウンドであることに賭けても構わないと思っています。より良いハードウェアを保存するための治療法はありません。

于 2012-09-25T18:19:14.130 に答える
4

FileChannel は ByteBuffers でのみ機能するため、自然にバッファリングされます。ByteBuffer から ByteBuffer にデータをコピーするために追加のバッファリングが必要な場合は、なぜそうしたいのかわかりません。

FileChannel は OS レベルでバッファリングを行います

FileChannel は OS に何をすべきかを伝えます。通常、OS にはディスク キャッシュがありますが、FileChannel はこれが事実であるかどうかわかりません。

Javaレベルでバッファリングしたい

選択の余地がないので、あなたは幸運です。;) これが唯一のオプションです。

于 2012-09-25T16:31:27.210 に答える
-2

2つのスレッドがあり、プロデューサースレッドはByteBufferを生成してキューの末尾に追加し、コンシューマースレッドは毎回キューの先頭からいくつかのByteBufferを削除し、fileChannel.write(ByteBuffer [])を呼び出します。

于 2012-09-25T16:56:48.977 に答える