我正在使用ruby绑定ruby-xz
。
random_string = SecureRandom.random_bytes(100)
compressed_string = XZ.compress(random_string, compression_level = 9, check = :none, extreme = true)
compressed_string.size # => always 148
我已经用不同长度的琴弦测试了数千次。
我知道至少有一半的字符串是1不可压缩的(不能超过1位压缩),3/4的字符串是2不可压缩的等等。(这是从计数参数开始的。) ,显然,没有说可压缩字符串数量的下限,但肯定有一些,不存在吗?
答案 0 :(得分:1)
有几个原因:
liblzma,当不处于RAW模式时,会添加一个描述字典大小的标题和一些其他设置。这是它增长的原因之一。
与许多其他压缩器一样,LZMA使用范围编码器以最少的位数编码字典压缩的输出(实质上是LZ77的badass版本)。因此,在比特流的末尾,填充最后的比特以使其成为一个完整的字节。
您正在压缩随机噪音,正如您所说,难以压缩。范围编码器试图找到最少量的比特来编码由字典压缩轮输出的符号。所以在这种情况下,会有很多符号。如果LZMA发现了一个(或两个)重复模式,那么最终它只能从输出中节省一两个。如第2点所述,您无法在字节级别上观察。
观察开销的一些小实验。
$ dd if=/dev/urandom bs=1k count=0 2>/dev/null | xz -9 -e --format=raw -c 2>/dev/null | wc -c
1
它需要至少一个或两个比特才能说它到达流的末尾,这被填充到一个字节
$ dd if=/dev/zero bs=1k count=1 2>/dev/null | xz -9 -e --format=raw -c 2>/dev/null | wc -c
19
非常好,但复杂性理论明智,仍然可能是几个字节到很多(1000x'\ 0'将是最佳编码)
$ dd if=/dev/zero bs=1k count=1 2>/dev/null | sed 's/\x00/\xFF/g'| xz -9 -e --format=raw -c 2>/dev/null | wc -c
21
有趣的是,xz压缩比全零更糟糕。很可能与LZMA字典在一定程度上有效(这是LZMA的新颖思想之一)有关。
$ dd if=/dev/urandom bs=1k count=1 2>/dev/null | xz -9 -e --format=raw -c 2>/dev/null | wc -c
1028
比输入多4个字节,还不错。
$ for i in {1..1000}; do dd if=/dev/urandom bs=1k count=1 2>/dev/null | xz -9 -e --format=raw -c 2>/dev/null | wc -c; done | sort | uniq -c
1000 1028
所以每次都需要1028个字节。