【问题标题】:Seeking out the optimum size for BufferedInputStream in Java在 Java 中寻找 BufferedInputStream 的最佳大小
【发布时间】:2010-12-14 10:22:03
【问题描述】:

我正在分析加载二进制文件的代码。加载时间约为 15 秒。

我的大部分加载时间来自加载二进制数据的方法。

我有以下代码来创建我的 DataInputStream:

is = new DataInputStream(
     new GZIPInputStream(
     new FileInputStream("file.bin")));

我把它改成了这样:

is = new DataInputStream(
     new BufferedInputStream(
     new GZIPInputStream(
     new FileInputStream("file.bin"))));

所以在我做了这个小修改后,加载代码从 15 秒变成了 4 秒。

但后来我发现 BufferedInputStream 有两个构造函数。另一个构造函数允许您显式定义缓冲区大小。

我有两个问题:

  1. 在 BufferedInputStream 中选择了什么大小,是否理想?如果没有,我怎样才能找到缓冲区的最佳大小?我应该编写一些执行二进制搜索的快速代码吗?
  2. 这是我可以使用 BufferedInputStream 的最佳方式吗?我最初在 GZIPInputStream 中拥有它,但好处可以忽略不计。我假设代码现在所做的是每次需要填充文件缓冲区时,GZIP 输入流都会通过并解码 x 字节(其中 x 是缓冲区的大小)。完全省略 GZIPInputStream 值得吗?绝对不需要,但是使用它时我的文件大小会大大减小。

【问题讨论】:

    标签: java optimization bufferedinputstream


    【解决方案1】:

    GZIPInputStream 和 BufferedInputStream 都使用内部缓冲区。这就是为什么在 GZIPInputStream 中使用 BufferedInputStream 没有任何好处的原因。 GZIPInputStream 的问题在于它不缓冲它生成的输出,因此您当前的版本要快得多。

    BufferedInputStream 的默认缓冲区大小为 8kb,因此您可以尝试增加或减少它以查看是否有帮助。我怀疑确切的数字是否重要,因此您可以简单地乘以或除以 2。

    如果文件很小,也可以尝试完全缓冲。这应该会给你理论上的最佳性能。您还可以尝试增加 GZIPInputStream 的缓冲区大小(默认为 512 字节),因为这可能会加快从磁盘读取的速度。

    【讨论】:

    • 我建议您在从磁盘读取时为 GZIPInputStream 尝试 64K 的缓冲区。我使用 1 MB,这可能超出了需要。 ;)
    【解决方案2】:
    1. 不要为编码二进制搜索而烦恼。只需手动尝试一些值并比较时间(如果您愿意,可以进行手动二进制搜索)。您很可能会发现非常宽泛的缓冲区大小可以为您提供接近最佳的性能,因此请选择可以解决问题的最小的。

    2. 你所拥有的是正确的顺序:

      is = new DataInputStream(
           new BufferedInputStream(
           new GZIPInputStream(
           new FileInputStream("file.bin"))));
      

      将BufferedInputStream 放在GZIPInputStream 中没有什么意义,因为后者已经缓冲了它的输入(但不是输出)。

      删除GZIPInputStream 可能是一个胜利,但如果数据必须从磁盘读取并且不驻留在文件系统缓存中,则很可能会损害性能。原因是从磁盘读取非常慢,而解压缩gzip 非常快。因此,从磁盘读取较少数据并在内存中解压缩通常比从磁盘读取更多数据更便宜。

    【讨论】:

      猜你喜欢
      • 2021-01-03
      • 1970-01-01
      • 2012-10-27
      • 2011-08-03
      • 2013-12-03
      • 1970-01-01
      • 2021-09-12
      相关资源
      最近更新 更多