我应该使用GzipOutputStream和BufferedOutputStream的顺序

2022-09-01 10:14:49

任何人都可以建议我是否应该做这样的事情:

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

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

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


答案 1

GZIPOutputStream已经带有一个内置缓冲区。因此,没有必要在链中将BufferedOutputStream放在它旁边。gojomo的出色答案已经为放置缓冲区的位置提供了一些指导。

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

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


答案 2

我应该使用什么顺序和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 MB 的范围内测试了 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%

推荐