当前位置: 首页 > 知识库问答 >
问题:

zlib deflate:为什么它会积累短数据,直到输入缓冲区满了才开始压缩?

严玉泽
2023-03-14

在zlib的deflate实现中,注意到当给定的数据长度较小时,zlib函数会将数据复制到输入缓冲区,只有当输入缓冲区满时才开始压缩。

当给定的数据长度大于输入缓冲区大小时,zlib函数直接开始压缩。

我想知道将短数据积累到输入缓冲区中有什么好处。我能想到的是:

  • 避免花费在块处理上的开销,包括Huffman树初始化和CRC caculation
  • 保持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;
}

共有1个答案

宰父夕
2023-03-14

deflate压缩数据格式由块组成,这些块具有依赖于块数据的标题。因此,deflate的输出每次都是一个块,在第一个块完成之前什么都不写(除了zlib或gzip头)。

Zlib的deflate会累积数据,直到生成16k个符号为止。符号可以是单个字节(以文字形式编码),也可以是长度/距离对,它对前面32K未压缩数据中最多258字节的副本进行编码。因此,在发出第一个块之前,您将积累16K到4MB的未压缩数据(对于高度可压缩的数据)。

一旦积累了数据,zlib决定要构造什么样的块,然后这样做,创建头部,对于动态块,头部描述了块中的霍夫曼码,然后为该块创建编码符号。或者创建一个存储的或静态的块,无论其结果是最少的比特数。只有这样,压缩数据才可用。

这是重复的,所以放气压缩的数据将出现在突发可用,如果你给它提供小的输入缓冲区。它在使用大输入缓冲区时做了完全相同的事情,但你只是不容易看到延迟,但它仍然存在。

 类似资料:
  • 问题内容: 从管道获取可能会返回StreamSpliterators.WrappingSpliterator的实例。例如,获取以下内容: 鉴于以上所述,当我们通过的方法(在本例中为StreamSpliterators.WrappingSpliterator的一个实例)单独遍历元素时,它将首先将项目累积到内部缓冲区中,然后再使用这些项目,如我们在StreamSpliterators.java中所看到

  • 我已经在网上搜索了几天这种现象,我可以找到一个类似问题的片段,这表明可能与底层的InputStreamReader和/或StreamDecoder有关,但这开始超出了我的专业知识。(见本链接) 所以我的问题是,我是否正确地实现了BufferedReader,以及如何解决我所看到的问题,以便在没有不必要的延迟的情况下获得每一行。

  • 我们正在迁移到Spring WebFlux(带有Reactornetty)。应用程序使用HTTP协议和Spring控制器。目前,我们有一种过渡解决方案,它将入站IO缓冲区累积到合成字节buf中,而不进行复制(然后将其作为输入流进行处理)。Reactornetty为我们提供直接字节缓冲区。因此,为这些缓冲区调用是至关重要的。最初我们有代码: 在处理得到的复合缓冲液后进行释放。 但当上游发布器发出错误

  • 我读到FileWriter和BufferedWriter的区别在于FileWriter直接写入文件(逐字符),white BufferedReader使用缓冲区。如果是,为什么FileWriter有缓冲区?例如,如果我创建一个FileWriter对象,如下所示: 而且,如果我在程序结束时不刷新或关闭写入器,它将不会向文件写入任何内容。这意味着它也使用缓冲区。拜托,解释一下?

  • 问题内容: 由于它不在jvm heap&gc中,何时发布?还是一直保留到流程终止? 但是所有答案都是模糊的,没有一个明确的答案,是否有明确的答案?至少适用于 64位Linux 上的 Java 8 。 __ 问题答案: 不使用旧的Java终结器。相反,它使用内部API。它创建一个新线程并存储到每个创建的线程中(除了重复和切片指的是主缓冲区)。当变成 幻影可到达的 (也就是说,不再存在对字节缓冲区的强

  • 问题内容: 在编写用于OpenGL库的Matrix类时,我遇到了一个问题,即使用Java数组还是使用Buffer策略存储数据(JOGL为Matrix操作提供直接缓冲区复制)。为了对此进行分析,我编写了一个小型性能测试程序,该程序比较了Arrays vs Buffers和Direct Buffers上循环和批量操作的相对速度。 我想在这里与您分享我的结果(因为我发现它们很有趣)。请随时发表评论和/或