【问题标题】:Deflate Compression Stream where pre compressed Data can be inserted. Does a .NET lib exist?Deflate Compression Stream 可以插入预压缩数据的位置。 .NET 库是否存在?
【发布时间】:2023-03-24 08:11:01
【问题描述】:

我正在为 Web 内容实施 Deflate 和 GZip 压缩。 .NET Framework DeflateStream 的性能非常好(它的压缩效果不如 SharpZipLib,但速度要快得多)。不幸的是,它(以及我知道的所有其他库)错过了写入预压缩数据的函数,例如 stream.WritePrecompressed(byte[] buffer)。

使用此功能,可以在流中插入预压缩块。这可以减少压缩这部分的 cpu 负载并增加 web 服务器的总吞吐量。

是否有任何托管库能够做到这一点?或者,除了 ComponentAce 的 ZLIB.NET 之外,还有什么好的起点可以做到这一点?

【问题讨论】:

  • 你确定有可能吗?使用 deflate 算法进行压缩会构建基于已压缩数据的内部数据结构,如果您将数据注入流中,则解压缩很可能不起作用,除非您在解压缩过程中也剥离了这些部分。
  • 是的,这应该是可能的,Deflate 流被组织在块中,压缩可以重新启动或更改。插入可以开始一个新的块。如果可能,插入的预压缩块也可能具有允许适应现有霍夫曼树的特殊标头。如果没有,它会开始一个新的。

标签: c# .net compression deflate


【解决方案1】:

另一种方法是刷新 deflater 流(也可能关闭它),以确保将所有缓冲的压缩数据写入输出流,然后简单地将预压缩数据写入底层输出流,然后重新打开再次将 deflater 流置于输出流之上。

【讨论】:

    【解决方案2】:

    IIRC #ZipLib 允许您设置压缩级别,您是否尝试过刷新流并将级别降至 0,然后在再次提高压缩级别之前发送已经压缩的数据?

    如果您只是出于性能原因考虑这样做,那么这可能是一个可以接受的解决方案。

    【讨论】:

    • 这是快速而肮脏的解决方案。事实上,只要您将生成的块标记为“不是最后一个”,它就适用于所有库。您可以简单地添加一个新块。如果插入的块为 5.000 字节或更大是可以接受的,因为向后距离限制为 32.768 字节,并且出于速度原因,算法通常只会使用 4.096 字节。
    【解决方案3】:

    是的,您可以将预压缩块插入到 zlib 流中。从 zlib 源代码中的 zpipe.c 示例开始。仅在要插入预压缩块的地方,将 Z_NO_FLUSH 替换为 Z_FULL_FLUSH(否则不要使用 Z_FULL_FLUSH,因为压缩率会受到影响。)

    现在压缩输出是字节对齐的,最后一个 deflate 块被关闭。完全刷新意味着经过预压缩块的下一个块不能包含任何反向引用。

    将您的预压缩块附加到输出流(例如 memcpy)。将 strm.next_out 推进到下一个空字节。从上次停止的地方继续放气。

    flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
    ret = deflate(&strm, flush);
    

    【讨论】:

      最近更新 更多