在Java中寻找BufferedInputStream的最佳大小

时间:2010-12-14 10:22:04

标签: java optimization bufferedinputstream

我正在分析正在加载二进制文件的代码。加载时间约为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?它绝对不需要,但使用它时我的文件大小会大大减少。

2 个答案:

答案 0 :(得分:8)

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

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

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

答案 1 :(得分:4)

  1. 不要打扰编码二进制搜索。只需手动尝试一些值并比较时间(如果您愿意,可以进行手动二分查找)。您很可能会发现,各种各样的缓冲区大小都会为您提供接近最佳的性能,因此请选择最小的缓冲区。

  2. 您拥有的是正确的订单:

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

    BufferedInputStream置于GZIPInputStream内是没有意义的,因为后者已经缓冲了它的输入(但不是输出。)

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