【问题标题】:Performance : BufferedOutputStream vs FileOutputStream in Java性能:Java 中的 BufferedOutputStream 与 FileOutputStream
【发布时间】:2017-09-17 14:11:39
【问题描述】:

我读过BufferedOutputStream类提高效率,必须以这种方式与FileOutputStream一起使用-

BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream("myfile.txt"));

对于写入同一个文件,下面的语句也是有效的 -

FileOutputStream fout = new FileOutputStream("myfile.txt");

但推荐的方法是使用 Buffer 进行读/写操作,这就是我也更喜欢使用 Buffer 的原因。

但我的问题是如何衡量上述 2 个语句的性能。他们是什么工具或某种东西,不知道到底是什么?但是这对于分析它的性能很有用。

作为 JAVA 语言的新手,我很想知道它。

【问题讨论】:

    标签: java


    【解决方案1】:

    缓冲仅在您进行低效阅读或写作时才有用。对于阅读,它有助于让您逐行阅读,即使您可以使用 read(byte[]) 或 read(char[]) 更快地吞噬字节/字符。对于写入,它允许您使用缓冲区缓冲要通过 I/O 发送的内容,并仅在刷新时发送它们(请参阅 PrintWriter (PrintOutputStream(?).setAutoFlush())

    但如果您只是想尽可能快地读取或写入,缓冲并不能提高性能

    一个高效读取文件的例子:

    File f = ...;
    FileInputStream in = new FileInputStream(f);
    byte[] bytes = new byte[(int) f.length()]; // file.length needs to be less than 4 gigs :)
    in.read(bytes); // this isn't guaranteed by the API but I've found it works in every situation I've tried
    

    相对于低效阅读:

    File f = ...;
    BufferedReader in = new BufferedReader(f);
    String line = null;
    while ((line = in.readLine()) != null) {
      // If every readline call was reading directly from the FS / Hard drive,
      // it would slow things down tremendously. That's why having a buffer 
      //capture the file contents and effectively reading from the buffer is
      //more efficient
    }
    

    【讨论】:

    • 阅读或写作效率低下是什么意思? @ControlAltDel
    • @user7876966 我已经用高效和低效阅读的例子更新了我的答案
    • 意味着从 FS / HDD 中已经可用的文件读取效率低下,从 cmd 读取(即用户输入数据)是有效的。这一切都取决于这种类型的读/写,我们应该在 BufferedReader / BufferedWriter 和 FileInputStream / FileOutputStream @ControlAltDel 之间切换
    • @user7876966 不,你不明白我写了什么
    • This article 表明使用缓冲流减少了系统调用,因此理论上使用它们应该总是更好。
    【解决方案2】:

    这些数字来自使用 SSD 的 MacBook Pro 笔记本电脑。

    • BufferedFileStreamArrayBatchRead (809716.60-911577.03 字节/毫秒)
    • BufferedFileStreamPerByte(136072.94 字节/毫秒)
    • FileInputStreamArrayBatchRead (121817.52-1022494.89 字节/毫秒)
    • FileInputStreamByteBufferRead (118287.20-1094091.90 字节/毫秒)
    • FileInputStreamDirectByteBufferRead (130701.87-956937.80 字节/毫秒)
    • FileInputStreamReadPerByte(1155.47 字节/毫秒)
    • RandomAccessFileArrayBatchRead (120670.93-786782.06 字节/毫秒)
    • RandomAccessFileReadPerByte(1171.73 字节/毫秒)

    如果数字有一个范围,它会根据所使用的缓冲区大小而变化。缓冲区越大,速度越快,通常在硬件和操作系统中的缓存大小附近。

    如您所见,单独读取字节总是很慢。将读取分批成块很容易。它可能是每毫秒 1k 和每毫秒 136k(或更多)之间的差异。

    这些数字有点旧,它们会因设置而有很大差异,但它们会给你一个想法。生成数字的代码可以在here 找到,编辑 Main.java 以选择要运行的测试。

    JMH 是编写基准测试的优秀(且更严格)的框架。学习如何使用JMH的教程可以在here找到。

    【讨论】:

      猜你喜欢
      • 2020-07-15
      • 2013-07-05
      • 2018-02-12
      • 2017-06-17
      • 2010-12-08
      • 1970-01-01
      • 2012-02-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多