5

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

2 回答 2

8

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

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

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

于 2010-12-14T10:36:02.093 回答
4
  1. 不要为编码二进制搜索而烦恼。只需手动尝试一些值并比较时间(如果您愿意,可以进行手动二进制搜索)。您很可能会发现非常广泛的缓冲区大小将为您提供接近最佳的性能,因此请选择能够解决问题的最小的。

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

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

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

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

于 2010-12-14T10:30:50.317 回答