[英]How to improve GZIP performance
目前,我确实有一个问题,这段代码将被调用> 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();
}
}
我已经尝试用ByteBuffer
替换ByteArrayOutputStream
,但是在创建时我不知道需要分配多少字节。
另外,我尝试使用Inflater
但偶然发现了此处描述的问题。
任何其他想法,我可以做些什么来改善此代码的性能。
更新#1
分析您的应用程序,以确保您确实在此功能上花费了可优化的时间。 调用该函数多少次无关紧要; 如果它在整个程序执行时间中所占的比例不大,那么优化就浪费了。
调整ByteArrayOutputStream
的大小。 默认缓冲区大小为32个字节,并且调整大小要求复制所有现有字节。 如果您知道解码后的数组大约为1k,请使用new ByteArrayOutputStream(2048)
。
使用预先分配的byte[]
一次读取一个块,而不是一次读取一个字节。 注意,必须使用read
的返回值作为write
的输入。 最好使用Jakarta Commons IOUtils.copy()之类的东西来避免错误。
我不确定它是否适用于您的情况,但是使用默认的GZIPInputStream缓冲区大小与增加到65536进行比较时,发现速度差异非常大。
示例:使用500M输入文件->
new GZIPInputStream(new FileInputStream(path.toFile())) // takes 4 mins to process
VS
new GZIPInputStream(new FileInputStream(path.toFile()), 65536) // takes 10s
Ĵ
可以在这里找到更多详细信息http://java-performance.info/java-io-bufferedinputstream-and-java-util-zip-gzipinputstream/
BufferedInputStream和GZIPInputStream都有内部缓冲区。 前一个的默认大小为8192字节,而后一个的默认大小为512字节。 通常值得将这些大小中的任何一个增加到至少65536。
您可以使用Inflater
类方法reset()
重用Inflater
对象,而不必每次都重新创建它。 您将需要做一些额外的编程工作,以便解码gzip标头并使用gzip预告片执行完整性检查。 然后,您可以将Inflater
与nowrap
选项一起使用,以在gzip标头之后和预告片之前解压缩原始的压缩数据。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.