2009-07-04 19 views

回答

25

我应该使用什么命令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次,并切断第一次运行和其余的平均。我也尝试了缓冲gzip缓冲,这对于对象来说稍微好一点,对文本来说更糟糕。我根本没有玩过缓冲区大小。


对于对象流,我测试了两个序列化的10兆字节的目标文件。对于较大的文件(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),它是用于读出(1.6对6.1秒)和40%的速度用于写入(2.8对4.7秒)快75%。它包含了大量的小物件。

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

对于文本读/写器我用了一个64MB的CSV文本文件。缓冲流周围的gzip流的读取速度(950对1070毫秒)要快11%,写时略快(7.9对8.1秒)。

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

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

6

当数据的最终目标是最好的读取/写入大块时,缓冲会有所帮助,否则您的代码会以其他方式推送它。所以你通常希望缓冲区尽可能靠近想要的地方。在你的例子中,这是被忽略的“...”,所以用GzipOutputStream包装BufferedOutputStream。并且,调整BufferedOutputStream缓冲区大小以匹配测试节目与目的地的最佳效果。

我怀疑在外面的BufferedOutputStream会帮助很多,如果有的话,没有明确的缓冲。为什么不? GzipOutputStream将在相同大小的块中将它的write()写成“...”,而不管外部缓冲是否存在。所以没有对“...”进行优化。你坚持使用什么尺寸的GzipOutputStream write()。

还请注意,您通过缓冲压缩数据而不是未压缩数据来更高效地使用内存。如果您的数据经常获得6X压缩,那么'内部'缓冲区相当于'外部'缓冲区6X。

0

阅读javadoc,您会发现BIS用于缓冲从某些原始源读取的字节。一旦你得到原始字节你想压缩它们,所以你用GIS包装BIS。缓冲来自GZIP的输出是没有意义的,因为需要考虑缓冲GZIP,谁来做这件事?

​​
+2

“你想压缩它们,所以你用GIS包装BIS” - GIS不压缩。它解压缩。 FWIW我在你的答案的后半部分努力理解你的一般观点。 – bacar 2013-10-19 17:52:50

2

通常你想有一个缓冲区接近你的FileOutputStream中(假设这是什么......代表),以避免过多调用到操作系统和频繁的磁盘访问。但是,如果您正在为GZIPOutputStream编写大量小块,那么您也可以从GZIPOS周围的缓冲区中受益。原因是GZIPOS中的写入方法是同步的,并且还导致其他几个同步调用和几个本地(JNI)调用(更新CRC32并进行实际压缩)。这些都会增加每次通话的额外开销。所以在这种情况下,我会说你会从两个缓冲区中受益。

17

GZIPOutputStream已经内置了缓冲区。所以,不需要在链中放置一个BufferedOutputStream。 gojomo的优秀答案已经提供了一些关于放置缓冲区的指导。

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

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

相关问题