10

今日の初めに退屈していたので、Javaでのバッファリングされたバイトストリームとバッファリングされていないバイトストリームの相対的なパフォーマンスについて少し考え始めました。簡単なテストとして、適度に大きなテキストファイルをダウンロードし、ファイルをコピーするときにバッファリングされたストリームが与える影響を判断するための短いプログラムを作成しました。4つのテストが実行されました。

  1. バッファリングされていない入力および出力バイトストリームを使用してファイルをコピーします。
  2. バッファリングされた入力ストリームとバッファリングされていない出力ストリームを使用してファイルをコピーします。
  3. バッファリングされていない入力ストリームとバッファリングされた出力ストリームを使用してファイルをコピーします。
  4. バッファリングされた入力ストリームと出力ストリームを使用してファイルをコピーします。

当然のことながら、バッファリングされた入力ストリームと出力ストリームを使用すると、バッファリングされていないストリームを使用するよりも桁違いに高速になります。ただし、(少なくとも私にとって)本当に興味深いのは、ケース2と3の速度の違いでした。いくつかのサンプル結果は次のとおりです。

Unbuffered input, unbuffered output
Time: 36.602513585

Buffered input, unbuffered output
Time: 26.449306847

Unbuffered input, buffered output
Time: 6.673194184

Buffered input, buffered output
Time: 0.069888689

興味のある方は、ここGithubでコードを入手できます。ケース2と3の時間が非常に非対称である理由を誰かが明らかにすることができますか?

4

3 に答える 3

10

ファイルを読み取ると、その下のファイルシステムとデバイスがさまざまなレベルのキャッシュを実行します。一度に1バイトを読み取ることはほとんどありません。彼らはブロックを読みます。次のバイトの後続の読み取りでは、ブロックはキャッシュにあるため、はるかに高速になります。

バッファサイズがブロックサイズと同じサイズである場合、入力ストリームをバッファリングしても実際にはそれほど多くは得られないのは当然です(いくつかのシステムコールを節約できますが、実際の物理I/Oに関してはあまり節約しません)。

ファイルを書き込むとき、書き込むもののバックログをファイルシステムに与えていないためファイルシステムはキャッシュできません。出力をバッファリングする可能性がありますが、バッファをフラッシュする頻度について知識に基づいた推測を行う必要があります。出力を自分でバッファリングすることにより、そのバックログを手動で構築するため、デバイスが一度にはるかに多くの作業を実行できるようになります。

于 2012-09-06T20:08:04.450 に答える
2

タイトルの質問に対しては、出力をバッファリングする方が効果的です。この理由は、ハードディスクドライブ(HDD)がセクターにデータを書き込む方法にあります。特に断片化されたディスクを検討します。ディスクはデータがどこにあるかをすでに認識しているので、データがどこに収まるかを判断する必要があるので、読み取りははるかに高速です。バッファを使用すると、ディスクは、バッファなしの方法よりも、データを保存するためのより大きな連続した空白スペースを見つけます。笑いのために別のテストを実行します。ディスク上に新しいパーティションを作成し、クリーンスレートの読み取りと書き込みのテストを実行します。リンゴとリンゴを比較するには、テスト間で新しく作成されたパーティションをフォーマットします。テストを実行する場合は、この後に番号を投稿してください。

于 2012-09-06T20:35:22.530 に答える
1

一般に、書き込みはコンピュータにとってより面倒です。読み取りはキャッシュできますが、キャッシュはキャッシュできないためです。一般的に、それは実際の生活とよく似ています-読むことは書くことよりも速くて簡単です!

于 2012-09-06T20:07:39.850 に答える