6

ByteBuffer.allocateDirect() を使用して、ファイルをメモリに読み込むためのバッファ メモリを割り当て、最終的にそのファイルのバイトをハッシュして、そこからファイル ハッシュ (SHA) を取得しています。入力ファイルのサイズは、数 KB から数 GB までさまざまです。

バッファサイズの選択に関して、いくつかのスレッドとページ (SO の一部も含む) を読みました。部分ブロックなどの読み取り操作の可能性を最小限に抑えるために、ネイティブ FileSystem が使用するものを選択することをお勧めする人もいます。4100 バイトのバッファーと NTFS の既定値は 4096 であるため、余分な 4 ビットは別の読み取り操作を必要とし、非常に無駄になります。

したがって、2、1024、2048、4096、8192 などの累乗に固執します。32KB のサイズの推奨バッファーを見たことがありますが、バッファーを入力ファイルのサイズにすることを推奨するものもあります (小さなファイルにはおそらく問題ありませんが、大きなファイルについて?)。

ネイティブのブロックサイズのバッファに固執することはどれほど重要ですか? 現代的に言えば(少なくとも8Mbのオンドライブキャッシュを備えた最新のSATAドライブ以上、およびI / Oを最適化するための他の最新のOS「魔法」を想定)バッファーサイズはどれほど重要であり、設定するサイズをどのように決定するのが最適ですか?静的に設定するか、動的に決定できますか? 洞察をありがとう。

4

1 に答える 1

6

あなたの直接の質問に答えるには:(1)ファイルシステムは2の累乗を使用する傾向があるため、同じことをしたいと考えています。(2) 作業バッファーが大きいほど、サイズのミスによる影響は少なくなります。

あなたが言うように、4100 を割り当て、実際のブロック サイズが 4096 の場合、バッファを埋めるために 2 回の読み取りが必要になります。代わりに、1,000,000 バイトのバッファーがある場合、1 ブロックの高低は問題になりません (そのバッファーを埋めるには 245 4096 バイトのブロックが必要なため)。さらに、バッファーが大きいということは、OS が読み取りを順序付けする可能性が高くなることを意味します。

とはいえ、これにはNIOを使用しません。代わりに、単純な を使用BufferedInputStreamし、s にはおそらく 1k のバッファを使用しread()ます。

NIO の主な利点は、Java ヒープからデータを除外することです。たとえば、InputStreamOS がデータを JVM 管理のバッファーに読み込む手段を使用して、ファイルの読み取りと書き込みを行う場合、JVM はそれをヒープ上のバッファーにコピーし、ヒープ外のバッファーに再度コピーします。 、次に OS はそのオフヒープ バッファーを読み取り、実際のディスク ブロックを書き込みます (通常は独自のバッファーを追加します)。この場合、NIO はそのネイティブ ヒープのコピーを削除します。

ただし、ハッシュを計算するには、データを Java ヒープに置く必要があり、MacSPIはデータをそこに移動します。そのため、NBI がデータをオフヒープに保持する利点が得られず、IMO の「古い IO」の方が書き込みが容易です。

要求したすべてのバイトを読み取ることが保証されてInputStream.read()ないことを忘れないでください。

于 2013-04-17T19:08:17.787 に答える