缩小和修复霍夫曼代码
Deflate and fixed Huffman codes
我正在尝试实现一个放气压缩器,我必须决定是否
使用静态霍夫曼代码压缩块或创建动态块。
与静态代码相关的长度背后的基本原理是什么?
(这是包含在 rfc 中的 table)
Lit Value Bits
--------- ----
0 - 143 8
144 - 255 9
256 - 279 7
280 - 287 8
我认为静态代码更偏向纯 ascii 文本,而不是
看起来它更喜欢压缩 rle 长度
决定是否使用静态代码的良好启发式是什么?
我正在考虑从以下样本中构建概率分布
输入数据并根据导出的概率计算距离(也许是 EMD?)
来自静态代码。
我猜测代码的创建者从压缩数据中提取了大量的文字和长度样本,可能包括 executables 和文本,并在大型集合中找到了典型的代码长度。然后用所示的 table 对它们进行近似。不过作者很多年前就去世了,所以我们永远无法确定。
你不需要启发式。完成查找匹配字符串的工作后,计算块中动态和静态表示的位数相对非常快。然后简单地选择较小的那个。或者静态的,如果相等(解码速度更快)。
我不知道原理,但是在选择静态代码长度时有少量不合理:
在你问题的table中,最大的静态代码数是287,但是DEFLATE specification只允许最多285个代码,这意味着代码长度被浪费地分配给了两个无效代码. (甚至最长的也不是!)这与距离代码的 table 类似,32 个代码分配了长度,但只有 30 个有效。
因此,可以进行一些简单的改进,但也就是说,如果没有对数据的一些先验知识,就不可能真正产生任何通常效率更高的东西。 table 的“平坦度”(没有超过 9 位的代码)将 worst-case 性能降低到每字节不可压缩数据 1 个额外位。
我认为分组背后的主要理由是,通过将组大小保持为 8 的倍数,可以通过查看 5 个最高有效位来判断代码属于哪个组,这也告诉您它的长度, 以及要添加什么值以立即获取代码值本身
00000 00 .. 00101 11 7 bits + 256 -> (256..279)
00110 000 .. 10111 111 8 bits - 48 -> ( 0..144)
11000 000 .. 11000 111 8 bits + 78 -> (280..287)
11001 0000 .. 11111 1111 9 bits - 256 -> (144..255)
因此理论上您可以设置包含 32 个条目的查找 table 以快速读取代码,但这种情况并不常见,可能不值得优化。
只有两种情况(有一些重叠)固定霍夫曼块可能是最有效的:
其中以字节为单位的输入大小非常小,Static Huffman 可以比 Uncompressed 更有效,因为 Uncompressed 使用 32 位 header,而 Fixed Huffman 只需要 7-位页脚,加上每字节 1 位潜在开销。
在输出大小非常小的情况下(即。small-ish,高度可压缩的数据),静态霍夫曼比动态霍夫曼更有效——同样是因为动态霍夫曼使用一定数量的space 额外 header。 (实际的最小 header 大小很难计算,但我会说至少 64 位,可能更多。)
也就是说,我发现从开发人员的角度来看它们实际上很有帮助,因为使用静态霍夫曼块很容易实现 Deflate-compatible 函数,并从那里迭代改进以获得更高效的算法正在工作。
我正在尝试实现一个放气压缩器,我必须决定是否 使用静态霍夫曼代码压缩块或创建动态块。
与静态代码相关的长度背后的基本原理是什么?
(这是包含在 rfc 中的 table)
Lit Value Bits
--------- ----
0 - 143 8
144 - 255 9
256 - 279 7
280 - 287 8
我认为静态代码更偏向纯 ascii 文本,而不是
看起来它更喜欢压缩 rle 长度
决定是否使用静态代码的良好启发式是什么?
我正在考虑从以下样本中构建概率分布 输入数据并根据导出的概率计算距离(也许是 EMD?) 来自静态代码。
我猜测代码的创建者从压缩数据中提取了大量的文字和长度样本,可能包括 executables 和文本,并在大型集合中找到了典型的代码长度。然后用所示的 table 对它们进行近似。不过作者很多年前就去世了,所以我们永远无法确定。
你不需要启发式。完成查找匹配字符串的工作后,计算块中动态和静态表示的位数相对非常快。然后简单地选择较小的那个。或者静态的,如果相等(解码速度更快)。
我不知道原理,但是在选择静态代码长度时有少量不合理:
在你问题的table中,最大的静态代码数是287,但是DEFLATE specification只允许最多285个代码,这意味着代码长度被浪费地分配给了两个无效代码. (甚至最长的也不是!)这与距离代码的 table 类似,32 个代码分配了长度,但只有 30 个有效。
因此,可以进行一些简单的改进,但也就是说,如果没有对数据的一些先验知识,就不可能真正产生任何通常效率更高的东西。 table 的“平坦度”(没有超过 9 位的代码)将 worst-case 性能降低到每字节不可压缩数据 1 个额外位。
我认为分组背后的主要理由是,通过将组大小保持为 8 的倍数,可以通过查看 5 个最高有效位来判断代码属于哪个组,这也告诉您它的长度, 以及要添加什么值以立即获取代码值本身
00000 00 .. 00101 11 7 bits + 256 -> (256..279)
00110 000 .. 10111 111 8 bits - 48 -> ( 0..144)
11000 000 .. 11000 111 8 bits + 78 -> (280..287)
11001 0000 .. 11111 1111 9 bits - 256 -> (144..255)
因此理论上您可以设置包含 32 个条目的查找 table 以快速读取代码,但这种情况并不常见,可能不值得优化。
只有两种情况(有一些重叠)固定霍夫曼块可能是最有效的:
其中以字节为单位的输入大小非常小,Static Huffman 可以比 Uncompressed 更有效,因为 Uncompressed 使用 32 位 header,而 Fixed Huffman 只需要 7-位页脚,加上每字节 1 位潜在开销。
在输出大小非常小的情况下(即。small-ish,高度可压缩的数据),静态霍夫曼比动态霍夫曼更有效——同样是因为动态霍夫曼使用一定数量的space 额外 header。 (实际的最小 header 大小很难计算,但我会说至少 64 位,可能更多。)
也就是说,我发现从开发人员的角度来看它们实际上很有帮助,因为使用静态霍夫曼块很容易实现 Deflate-compatible 函数,并从那里迭代改进以获得更高效的算法正在工作。