缓冲输出流比Java中的输入流更有效吗?

时间:2012-09-06 20:00:33

标签: java stream

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

  1. 使用无缓冲的输入和输出字节流复制文件。
  2. 使用缓冲的输入流和无缓冲的输出流复制文件。
  3. 使用无缓冲的输入流和缓冲的输出流复制文件。
  4. 使用缓冲的输入和输出流复制文件。
  5. 毫不奇怪,使用缓冲的输入和输出流比使用无缓冲的流快几个数量级。然而,真正有趣的事情(至少对我而言)是案例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
    

    对于有兴趣的人,代码可用here at Github。任何人都可以解释为什么案例2和案例3的时间如此不对称?

3 个答案:

答案 0 :(得分:10)

当您读取文件时,其下面的文件系统和设备会执行各种级别的缓存。他们几乎从不读过一个字节;他们看了一块。在随后读取下一个字节时,该块将位于缓存中,因此速度会快得多。

有理由认为,如果你的缓冲区大小与块大小相同,那么缓冲输入流实际上并没有获得那么多(它节省了一些系统调用,但就实际物理而言) / O它不会为你节省太多的钱。)

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

答案 1 :(得分:2)

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

答案 2 :(得分:1)

一般来说,写入对计算机来说比较繁琐,因为它在读取时无法缓存。一般来说,它与现实生活非常相似 - 阅读比写作更快更容易!