zlib deflate:为什么它会累积短数据并且直到输入缓冲区已满才开始压缩?
zlib deflate: why does it accumulate short data and doesn't start compression until input buffer is full?
在zlib的deflate实现中,注意到当给定的数据长度较小时,zlib函数会将数据复制到输入缓冲区,只有当输入缓冲区已满时才开始压缩。
当给定数据的长度大于输入缓冲区大小时,zlib 函数直接开始压缩。
默认输入缓冲区大小为 8KB。
我想知道将短数据累积到输入缓冲区的好处。我能想到的是:
- 避免花费在块处理上的开销,包括霍夫曼树初始化和 CRC 计算
- Keep I/O 适用于 8KB(或更大)的块,有利于性能
哪位知道更多的人可以和我分享一下你的想法,或者给我一些参考吗?
相关代码:
if (len < state->size) {
/* copy to input buffer, compress when full */
do {
if (strm->avail_in == 0)
strm->next_in = state->in;
n = state->size - strm->avail_in;
if (n > len)
n = len;
memcpy(strm->next_in + strm->avail_in, buf, n);
strm->avail_in += n;
state->x.pos += n;
buf = (char *)buf + n;
len -= n;
if (len && gz_comp(state, Z_NO_FLUSH) == -1)
return 0;
} while (len);
}
else {
/* consume whatever's left in the input buffer */
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
return 0;
/* directly compress user buffer to file */
strm->avail_in = len;
strm->next_in = (voidp)buf;
state->x.pos += len;
if (gz_comp(state, Z_NO_FLUSH) == -1)
return 0;
}
deflate 压缩数据格式由块组成,块具有依赖于块数据的header。因此 deflate 的输出一次一个块,在第一个块完成之前什么都不写(除了 zlib 或 gzip header)。
zlib 的 deflate 会累积数据,直到默认设置生成 16K 个符号。符号可以是单个字节,编码为文字,也可以是 length/distance 对,它在前面的 32K 未压缩数据中的某处编码最多 258 个字节的副本。因此,在发出第一个块之前,您将积累 16K 到 4MB 的未压缩数据(对于高度可压缩的数据)。
一旦积累了数据,zlib 就会决定构建什么样的块,然后创建 header,对于动态块,它描述块中的霍夫曼代码,然后创建该块的编码符号。或者它创建一个存储的或静态的块,无论结果是最少的位数。只有这样压缩数据才可用。
这会重复进行,因此如果您向其提供较小的输入缓冲区,则 deflate 压缩数据将以突发形式出现。它对大输入缓冲区做完全相同的事情,但你只是看不到延迟,但它仍然存在。
在zlib的deflate实现中,注意到当给定的数据长度较小时,zlib函数会将数据复制到输入缓冲区,只有当输入缓冲区已满时才开始压缩。
当给定数据的长度大于输入缓冲区大小时,zlib 函数直接开始压缩。
默认输入缓冲区大小为 8KB。
我想知道将短数据累积到输入缓冲区的好处。我能想到的是:
- 避免花费在块处理上的开销,包括霍夫曼树初始化和 CRC 计算
- Keep I/O 适用于 8KB(或更大)的块,有利于性能
哪位知道更多的人可以和我分享一下你的想法,或者给我一些参考吗?
相关代码:
if (len < state->size) {
/* copy to input buffer, compress when full */
do {
if (strm->avail_in == 0)
strm->next_in = state->in;
n = state->size - strm->avail_in;
if (n > len)
n = len;
memcpy(strm->next_in + strm->avail_in, buf, n);
strm->avail_in += n;
state->x.pos += n;
buf = (char *)buf + n;
len -= n;
if (len && gz_comp(state, Z_NO_FLUSH) == -1)
return 0;
} while (len);
}
else {
/* consume whatever's left in the input buffer */
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
return 0;
/* directly compress user buffer to file */
strm->avail_in = len;
strm->next_in = (voidp)buf;
state->x.pos += len;
if (gz_comp(state, Z_NO_FLUSH) == -1)
return 0;
}
deflate 压缩数据格式由块组成,块具有依赖于块数据的header。因此 deflate 的输出一次一个块,在第一个块完成之前什么都不写(除了 zlib 或 gzip header)。
zlib 的 deflate 会累积数据,直到默认设置生成 16K 个符号。符号可以是单个字节,编码为文字,也可以是 length/distance 对,它在前面的 32K 未压缩数据中的某处编码最多 258 个字节的副本。因此,在发出第一个块之前,您将积累 16K 到 4MB 的未压缩数据(对于高度可压缩的数据)。
一旦积累了数据,zlib 就会决定构建什么样的块,然后创建 header,对于动态块,它描述块中的霍夫曼代码,然后创建该块的编码符号。或者它创建一个存储的或静态的块,无论结果是最少的位数。只有这样压缩数据才可用。
这会重复进行,因此如果您向其提供较小的输入缓冲区,则 deflate 压缩数据将以突发形式出现。它对大输入缓冲区做完全相同的事情,但你只是看不到延迟,但它仍然存在。