繁体   English   中英

我应该使用GzipOutputStream和BufferedOutputStream的顺序

[英]What order should I use GzipOutputStream and BufferedOutputStream

任何人都可以推荐我是否应该这样做:

os = new GzipOutputStream(new BufferedOutputStream(...));

要么

os = new BufferedOutputStream(new GzipOutputStream(...));

哪个更有效率? 我应该使用BufferedOutputStream吗?

我应该使用GzipOutputStreamBufferedOutputStream顺序

对于对象流,我发现将gzip流周围的缓冲流包装为输入和输出几乎总是明显更快。 物体越小,这就越好。 在所有情况下都更好或相同,然后没有缓冲流。

ois = new ObjectInputStream(new BufferedInputStream(new GZIPInputStream(fis)));
oos = new ObjectOutputStream(new BufferedOutputStream(new GZIPOutputStream(fos)));

然而 ,对于文本和直字节流,我发现它是一个折腾 - 缓冲流周围的gzip流只是略微好一点。 但在所有情况下都更好,然后没有缓冲流。

reader = new InputStreamReader(new GZIPInputStream(new BufferedInputStream(fis)));
writer = new OutputStreamWriter(new GZIPOutputStream(new BufferedOutputStream(fos)));

我运行了每个版本20次并切断了第一次运行并平均了其余部分。 我也尝试过buffered-gzip-buffered,它对于对象稍微好一些,对文本来说更糟糕。 我根本没玩缓冲区大小。


对于对象流,我测试了10兆字节的2个序列化目标文件。 对于较大的文件(38mb),读取速度提高了85%(0.7对5.6秒),但实际写入速度稍慢(5.9对5.7秒)。 这些对象中包含一些大型数组,这可能意味着更大的写入。

method       crc     date  time    compressed    uncompressed  ratio
defla   eb338650   May 19 16:59      14027543        38366001  63.4%

对于较小的文件(18mb),读取速度提高了75%(1.6对6.1秒),写入速度提高了40%(2.8对4.7秒)。 它包含大量小物件。

method       crc     date  time    compressed    uncompressed  ratio
defla   92c9d529   May 19 16:56       6676006        17890857  62.7%

对于文本读写器,我使用了64mb csv文本文件。 缓冲流周围的gzip流读取速度快11%(950对1070毫秒),写入时略快(7.9对8.1秒)。

method       crc     date  time    compressed    uncompressed  ratio
defla   c6b72e34   May 20 09:16      22560860        63465800  64.5%

GZIPOutputStream已经内置了一个缓冲区。 因此,没有必要在链中放置一个BufferedOutputStream。 gojomo的优秀答案已经提供了缓冲区放置的一些指导。

GZIPOutputStream的默认缓冲区大小仅为512字节,因此您需要通过构造函数参数将其增加到8K甚至64K。 BufferedOutputStream的默认缓冲区大小为8K,这就是为什么在组合默认GZIPOutputStream和BufferedOutputStream时可以测量优势的原因。 通过适当调整GZIPOutputStream的内置缓冲区大小,也可以实现这一优势。

所以,回答你的问题: “我应该使用BufferedOutputStream吗?” →不,在您的情况下,您不应该使用它,而是将GZIPOutputStream的缓冲区设置为至少8K。

当数据的最终目的地以更大的块读取/写入时,缓冲有助于比您的代码推送它更大的块。 所以你通常希望缓冲尽可能接近那些想要更大块的地方。 在您的示例中,这是省略的“...”,因此使用GzipOutputStream包装BufferedOutputStream。 并且,调整BufferedOutputStream缓冲区大小以匹配测试显示最适合目标的测试。

我怀疑外面的BufferedOutputStream会有多大帮助,如果有的话,没有明确的缓冲。 为什么不? 无论外部缓冲是否存在,GzipOutputStream都会以相同大小的块执行write()s到“...”。 所以没有“......”可能的优化; 你坚持使用GzipOutputStream write()s的大小。

另请注意,通过缓冲压缩数据而不是未压缩数据,您可以更有效地使用内存。 如果你的数据经常实现6X压缩,那么'inside'缓冲区相当于6X的“外部”缓冲区。

通常你需要一个接近你的FileOutputStream的缓冲区(假设它代表什么),以避免过多的OS调用和频繁的磁盘访问。 但是,如果你在GZIPOutputStream中写了很多小块,你也可以从GZIPOS周围的缓冲区中受益。 原因是GZIPOS中的写入方法是同步的,并且还导致很少的其他同步调用和几个本机(JNI)调用(更新CRC32并进行实际压缩)。 这些都会增加每个呼叫的额外开销。 所以在这种情况下我会说你会从两个缓冲区中受益。

我建议你尝试一个简单的基准测试来计算压缩大文件所需的时间,看看它是否有很大的不同。 GzipOutputStream确实有缓冲但它是一个较小的缓冲区。 我会用64K缓冲区做第一个,但你可能会发现两者都做得更好。

读取javadoc,您会发现BIS用于缓冲从某些原始源读取的字节。 获得原始字节后,您需要压缩它们,以便使用GIS包装BIS。 缓冲GZIP的输出是没有意义的,因为需要考虑如何缓冲GZIP,谁会这样做呢?

new GzipInputStream( new BufferedInputStream ( new FileInputXXX

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM