【问题标题】:Is it more effective to buffer an output stream than an input stream in Java?在Java中缓冲输出流比输入流更有效吗?
【发布时间】:2012-09-06 20:00:33
【问题描述】:

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

  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

对于那些感兴趣的人,代码是可用的here at Github。谁能解释为什么案例 2 和 3 的时间如此不对称?

【问题讨论】:

  • 我会说无缓冲读取比无缓冲写入快....
  • @beny23 我想他明白了,他在问为什么
  • 在读取数据时,您应该首先通过多次调用相同的函数来触发 JIT。在你的情况下说 10 次。然后在每个方法之后你应该调用 GC,这样它就不会干预任何特定的结果。因为在您当前的代码中,如果您更改顺序,结果会有所不同
  • 当您在每个后续测试中重新读取文件时,您几乎可以肯定是从缓存而不是磁盘文件中读取它,因此您的测试实际上是无效的。您必须找到一种方法来在每次测试运行之间取消缓存。
  • @EJP 谢谢。我已经尝试过了,你是对的:确保在后续测试之前刷新缓存会显着降低性能。不过大体模式还是一样的。

标签: java stream


【解决方案1】:

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

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

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

【讨论】:

  • 这与大多数 HDD readwrite 以几乎相同的速度相吻合。那么问题来了,你给驱动器写东西的效率有多高。
  • “当你写一个文件时,文件系统不能缓存”不完全是:Linux(以及我使用过的所有其他“真实”操作系统,包括最新版本的 Windows)确实维护要写入磁盘的脏页缓存(这就是存在 sync 的原因)。
  • @parsifal:谢谢,这就是我试图通过说它可以缓冲输出来达到的目的。但你是对的,它不仅仅是一个缓冲区,因为后续读取也会从该缓存中读取。我更想说的是“它无法预测你接下来要写什么”,就像阅读一样。
  • 干杯马克,这是一个很好的解释。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    通常写入对于计算机来说比较乏味,因为它无法缓存而读取可以。一般来说,这很像现实生活中的情况——阅读比写作更快、更容易!

    【讨论】:

      猜你喜欢
      • 2017-06-09
      • 1970-01-01
      • 2014-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-02
      相关资源
      最近更新 更多