10

今天早些时候感到无聊,我开始思考 Java 中缓冲和非缓冲字节流的相对性能。作为一个简单的测试,我下载了一个相当大的文本文件并编写了一个简短的程序来确定缓冲流在复制文件时的效果。进行了四项测试:

  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

当你读取一个文件时,它下面的文件系统和设备会做不同级别的缓存。他们几乎从不一次读取一个字节;他们读了一个块。在随后读取下一个字节时,该块将在缓存中,因此速度会快得多。

因此,如果您的缓冲区大小与块大小相同,那么缓冲输入流实际上并不会为您带来太多好处(它节省了一些系统调用,但就实际的物理 I/O 而言不会为您节省太多)。

当你一个文件时,文件系统不能为你缓存,因为你没有给它积压的东西要写。它可能会为您缓冲输出,但它必须对刷新缓冲区的频率做出有根据的猜测。通过自己缓冲输出,您可以让设备一次完成更多工作,因为您手动建立了积压工作。

于 2012-09-06T20:08:04.450 回答
2

对于您的标题问题,缓冲输出更有效。原因是硬盘驱动器 (HDD) 将数据写入其扇区的方式。特别是考虑到碎片磁盘。读取速度要快得多,因为磁盘已经知道数据的位置,而不必确定它适合的位置。使用缓冲区,磁盘将找到比无缓冲方式更大的连续空白空间来保存数据。再进行一次测试以获取咯咯笑声。在磁盘上创建一个新分区并运行测试读取和写入到干净的状态。要将苹果与苹果进行比较,请在测试之间格式化新创建的分区。如果您进行测试,请在此之后发布您的号码。

于 2012-09-06T20:35:22.530 回答
1

通常,写入对于计算机来说更加繁琐,因为它无法缓存而读取可以。一般来说,它就像在现实生活中一样——阅读比写作更快、更容易!

于 2012-09-06T20:07:39.850 回答