如何提高GZIP性能

时间:2015-09-13 13:38:51

标签: java performance gzip

目前我确实遇到了这段代码被称为> 500k次的问题。压缩byte[]的大小小于1KB。每次调用该方法时,都必须创建所有流。所以我正在寻找一种改进此代码的方法。

private byte[] unzip(byte[] data) throws IOException, DataFormatException {

    byte[] unzipData = new byte[4096];

    try (ByteArrayInputStream in = new ByteArrayInputStream(data);
         GZIPInputStream gzipIn = new GZIPInputStream(in);
         ByteArrayOutputStream out = new ByteArrayOutputStream()) {

        int read = 0;
        while( (read = gzipIn.read(unzipData)) != -1) {
            out.write(unzipData, 0, read);
        }

        return out.toByteArray();
    }
}

我已triedByteArrayOutputStream替换ByteBuffer,但在创建时我不知道需要分配多少字节。

此外,我尝试使用Inflater,但我偶然发现了here描述的问题。

我还想知道如何改善此代码的性能。

更新#1

  • 也许this lib可以帮助某人。
  • 还有一个开放的JDK-Bug

3 个答案:

答案 0 :(得分:2)

  1. 描述您的应用程序,以确保您真正在此功能上花费了大量时间。你调用这个函数的次数并不重要;如果它没有占到整个程序执行时间的很大一部分,那么就会浪费优化。

  2. 预先调整ByteArrayOutputStream的大小。默认缓冲区大小为32个字节,调整大小需要复制所有现有字节。如果您知道解码后的阵列大约为1k,请使用new ByteArrayOutputStream(2048)

  3. 不是一次读取一个字节,而是使用预先分配的byte[]一次读取一个块。请注意,您必须使用read的返回值作为write的输入。更好的是,使用Jakarta Commons enter image description here之类的东西来避免错误。

答案 1 :(得分:0)

您可以使用Inflater类方法reset()重用Inflater对象,而无需每次都重新创建它。您将有一些额外的编程要做,以解码gzip标头并使用gzip预告片执行完整性检查。然后,您可以使用Inflaternowrap选项在gzip标头之后和预告片之前解压缩原始放气数据。

答案 2 :(得分:0)

我不确定它是否适用于您的情况,但是使用默认的GZIPInputStream缓冲区大小与增加到65536进行比较时,我发现了惊人的速度差异。

示例:使用500M输入文件->

new GZIPInputStream(new FileInputStream(path.toFile())) // takes 4 mins to process

vs

new GZIPInputStream(new FileInputStream(path.toFile()), 65536) // takes 10s

J

更多详细信息,请点击此处http://java-performance.info/java-io-bufferedinputstream-and-java-util-zip-gzipinputstream/

  

BufferedInputStream和GZIPInputStream都有内部缓冲区。   前一个的默认大小是8192字节,而后一个的默认大小   是512个字节。通常值得将这些大小中的任何一个增加到   至少65536。