C#快速/高效地压缩大量数据块

C#快速/高效地压缩大量数据块,c#,compression,block,C#,Compression,Block,我有大约270k个数据块对,每对由一个32KiB和一个16KiB块组成 当我将它们保存到一个文件时,我当然会得到一个非常大的文件。 但是数据很容易压缩。 使用WinRAR压缩5.48GiB文件后,经过强压缩,得到的文件大小为37.4MiB 但是我需要对每个块进行随机访问,因此我只能单独压缩块。 为此,我使用了.NET提供的Deflate类,它将文件大小减少到382MiB(我可以接受)。 但是速度不够快 很多速度损失可能是因为总是为每个块创建一个新的MemoryStream和Deflate实例。

我有大约270k个数据块对,每对由一个32KiB和一个16KiB块组成

当我将它们保存到一个文件时,我当然会得到一个非常大的文件。 但是数据很容易压缩。
使用WinRAR压缩5.48GiB文件后,经过强压缩,得到的文件大小为37.4MiB

但是我需要对每个块进行随机访问,因此我只能单独压缩块。
为此,我使用了.NET提供的Deflate类,它将文件大小减少到382MiB(我可以接受)。
但是速度不够快

很多速度损失可能是因为总是为每个块创建一个新的MemoryStream和Deflate实例。 但它们似乎不是为重复使用而设计的

我想,如果使用“全局”字典,而不是为每个块使用一个字典,则可以实现更好的压缩

是否有适合该任务的压缩算法(最好是C#)的实现

以下链接包含每个字节数出现的百分比,分为三种块类型(仅32KiB块)。 第一个和第三个区块类型的产状分别为37.5%和25%。

长档短篇故事: 类型1主要由类型1组成。 类型2主要由0和1组成 Type3主要由零组成 不会出现大于128的值(尚未出现)


16KiB块几乎总是由零组成

如果你想尝试不同的压缩,你可以从适合你的数据的RLE开始——即使在最简单的实现中,它也会非常快。如果你想拥有或找到某人的实现,相关的包含更多的链接,可以从其他算法开始


随机评论:“…大量的速度损失可能是…”并不是解决性能问题的方法。测量并看看它是否真的是这样。

无论你怎么努力,你都无法随机访问放气流(除非你放弃了LZ77部分,但这正是你现在压缩比如此之高的主要原因——即使如此,也有一些棘手的问题需要回避)。这是因为压缩数据的一部分被允许引用前一部分(最多32K字节),这也可能反过来引用另一部分,等等。因此,即使您确切知道压缩流中的数据位置(目前您不知道),您也必须从头开始解码流以获取所需的数据

但是,您可以使用一个流将多个(但不是全部)块压缩在一起。然后你会得到相当好的速度和压缩,但你不必解压所有的块来得到你想要的;只是您的块恰好所在的特定块。您需要一个额外的索引来跟踪每个压缩块在文件中的起始位置,但这是相当低的开销。可以把它看作是将所有内容压缩在一起(这对于压缩很好,但是对于随机访问很糟糕)和单独压缩每个块(对于随机访问很好,但是对于压缩和速度很差)之间的一种折衷办法。

Gzip被认为是“好的”,这意味着压缩比很好,速度也很好。 如果您想要更多的压缩,还有其他替代方案,例如7z

如果您想要更高的速度(这似乎是您的目标),则更快的替代方案将提供显著的速度优势,但代价是降低一些压缩效率。“重要”应转换为快很多倍,如5x-10x。这种算法最适合于“内存中”压缩场景,例如您的场景,因为它们使访问压缩块几乎毫无痛苦

例如,Clayton Stangeland刚刚发布了C#的LZ4。源代码在BSD许可证下提供:

项目主页上有一些与gzip的比较指标,例如:

i5 memcpy 1658 MB/s
i5 Lz4 Compression 270 MB/s Decompression 1184 MB/s  
i5 LZ4C# Compression 207 MB/s Decompression 758 MB/s 49%
i5 LZ4C# whole corpus Compression 267 MB/s Decompression 838 MB/s Ratio 47%
i5 gzip whole corpus Compression 48 MB/s Decompression 266 MB/s Ratio 33%

希望这能有所帮助。

实际上,在deflate中,字典限制为32K(一个“滑动窗口”,在添加每个输入字节时删除最旧的字节)。您是否愿意编写自己的压缩器/解压缩器?+1用于RLE和基准测试注释。RLE+Huffman编码可能会提供相当好的压缩,并且比常规的deflate更快。当然,哈夫曼编码有点复杂。RLE似乎已经获得了成功。在对数据结构进行一些修改以优化RLE后,它现在很容易与deflate竞争。而RLE的尺寸只是稍微大一点,我有一些想法来进一步优化它。