Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中,缓冲输出流是否比缓冲输入流更有效?_Java_Stream - Fatal编程技术网

在Java中,缓冲输出流是否比缓冲输入流更有效?

在Java中,缓冲输出流是否比缓冲输入流更有效?,java,stream,Java,Stream,今天早些时候我很无聊,我开始思考Java中缓冲字节流和非缓冲字节流的相对性能。作为一个简单的测试,我下载并编写了一个简短的程序,以确定复制文件时缓冲流的效果。进行了四项试验: 使用未缓冲的输入和输出字节流复制文件 使用缓冲输入流和非缓冲输出流复制文件 使用未缓冲的输入流和缓冲的输出流复制文件 使用缓冲输入和输出流复制文件 毫不奇怪,使用缓冲输入和输出流比使用非缓冲流快几个数量级。然而,真正有趣的事情(至少对我来说)是案例2和案例3之间的速度差异。部分样本结果如下: Unbuffered inpu

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

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

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

    一般来说,对于计算机来说,写入更为乏味,因为它无法缓存,而读取则可以。一般来说,这和现实生活很相似——阅读比写作更快更容易

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

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


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

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

    我想说无缓冲读取比无缓冲写入快。@beny23我想他是意识到了这一点,他问为什么。在读取数据时,您应该先调用相同的函数来触发JIT。对你的情况说10次。然后在每个方法之后,您应该调用GC,这样它就不会干预任何特定的结果。因为在您当前的代码中,如果更改顺序,则在每次后续测试中重新读取文件时,结果会有所不同,几乎可以肯定您是从缓存而不是磁盘文件中读取的,因此您的测试实际上无效。您必须找到一种方法在每次测试运行之间取消缓存的初始化。@EJP感谢您的帮助。我已经尝试过了,你是对的:在后续测试之前确保刷新缓存会导致性能显著下降。不过,一般的模式还是一样的。这与大多数硬盘和硬盘的速度几乎相同的事实相矛盾。因此,接下来的问题是如何有效地为驱动器写入内容。“当您写入文件时,文件系统无法缓存”不完全是:Linux(以及我使用过的所有其他“真实”操作系统,包括最新版本的Windows)确实维护了要写入磁盘的脏页缓存(这就是
    sync
    存在的原因)@parsifal:谢谢,这就是我想说的,它可以缓冲输出。但你是对的,它不仅仅是一个缓冲区,因为后续的读取也会从缓存中读取。我更想说的是“它无法预测你下一步要写什么”,就像阅读一样。干杯,马克,这是一个很好的解释。