3

私は使っている:

PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("test.txt"),1024*1024*500))

大きなファイル(約2GB)を書き込む。書き込みには26秒かかります。しかし、500 を 10/20 に置き換えると、19 秒かかります。

ここから、私が理解したのは、バッファリングによりパフォーマンスが向上することです。もしそうなら、なぜこれが起こっているのですか?5回ずつ実行して確認したので、システム/IO負荷は問題ありません。

4

6 に答える 6

2

前の質問で述べたように、最適なバッファー サイズ (通常は約 32 KB) があり、バッファーをこれより大きくすると、速度は遅くなります。デフォルトのバッファ サイズは 8 KB です。

ところで: L2/L3 CPU キャッシュの大きさは? (約 10 MB だと思います) プライマリ L1 キャッシュは約 32 KB ですか?

最速のキャッシュに収まるバッファを使用することで、最速のメモリを使用しています。メインメモリにのみ収まるバッファを使用することで、最も遅いメモリを使用しています (10 倍も遅くなります)。


あなたの質問に答えて。

私がしていることは、ISO-8859-1エンコーディング、つまり(byte) ch、一度に 1 バイトずつ ByteBuffer に書き込み、おそらくメモリ マップされていると仮定することです。

ガベージを作成せずに、ByteBuffer から書き込み/読み取りlongを行うためのメソッドがあります。double

https://github.com/peter-lawrey/Java-Chronicle/blob/master/src/main/java/vanilla/java/chronicle/impl/AbstractExcerpt.java

このアプローチを使用すると、1 秒あたり約 500 万行をディスクに記録できます。

于 2012-04-13T15:16:22.557 に答える
2

バッファーが大きすぎると、パフォーマンスが低下します。約 32 ~ 64 kb の IMO に固執する

于 2012-04-13T15:17:26.810 に答える
1

まず、それほど大きなバッファは必要ありません。通常、64K または 8K 程度の低さでも、降下 IO パフォーマンスを得るには十分です。バッファが大きくなると、IO レイヤーで大量のデータを書き込む時間が長くなるため、メモリと CPU が浪費されるだけです。したがって、IO を待機することと、単にメモリに書き込むこととの間のトレードオフ (計算を理解している場合は最小 - 最大) です。内部に固定サイズのバッファがあるため、巨大なバッファを IO デバイスに押し込むことはできません。ポイントは、可能な限り一致させることですが、他の処理が何をしているのかわからないため、それを行うのは比較的不可能であることに気付きました。最善の方法は、8K ~ 16K の低いものを試して実行し、測定することです。バッファを 32K の 2 倍にするなどして、実行し、測定します。速度が向上した場合は、もう一度やり直してください。

したがって、2GB のデータを 26 秒で書き込んだ場合、スループットは 76MB/秒または 650Mbit/秒になります。バッファサイズを妥当なものに下げるだけで、おそらく改善できます。

于 2012-04-13T15:24:19.077 に答える
1

I/O をバッファリングすると、実行されるシステム コールの数が減るため、パフォーマンスがある程度向上します。しかし、システム コールはそれほど高価ではなく (おそらくミリ秒程度)、バッファが大きすぎると他の領域で問題が発生する可能性があります。例えば:

  • 500M バイトのバッファは大量のメモリを使用し、GC オーバーヘッドを増やしたり、システムのページング負荷を増やしたりする可能性があります。

  • 1 回の書き込み呼び出しで 500M バイトを書き込むと、システムのバッファー キャッシュが飽和状態になり、アプリケーション レベルで他のことを行うことでディスク書き込みをオーバーラップさせる能力を圧倒する可能性があります。

(かなり)小さいバッファを使用してみてください。(個人的には、アプリケーション固有の調整を行わずに 8kb を超えるバッファーを使用することはありません。)

于 2012-04-13T15:29:17.220 に答える
1

1024*1024*500は 500 メガバイトです。基本的に、JVM に 500 MB の連続したメモリ ブロックを割り当てるように強制しています。これは、JVM がおそらく GC サイクルを実行する必要があるためです。

于 2012-04-13T15:17:11.497 に答える
1

非常に大きなバッファ (500 MB) も適切ではありません。これは、OS がその巨大なバイト バッファのメモリ管理を行うのがより困難になるためです。

箱を移動する代わりに、家のテーブルを移動することと比較してください。しかし、箱が小さくなりすぎると、何度も行き来しなければならなくなります。

メモリの割り当ては操作であることを忘れないでくださいO(n)

于 2012-04-13T15:17:19.000 に答える