来源:https://openzl.org/blog/2026-09-29-lz-in-openzl/
OpenZL 中的 LZ
从 v0.2.0 开始,OpenZL 自带原生 LZ 引擎,相比使用 Zstandard 或 LZ4,它可以提供更好的性能。虽然 OpenZL 的主要目标是结构化数据,但 LZ 仍然是几乎所有压缩图中使用的核心后端压缩技术,在去除了更高阶的结构之后应用。此外,在数据结构未知的用例中,LZ 是一个很好的默认选择。
OpenZL 的原生 LZ 引擎能比 Zstandard 或 LZ4 提供更好性能,主要有两个原因:
线格式:当不受线格式约束时,我们可以提供更好的性能。过去十年我们一直在优化 Zstandard 和 LZ4,但有些优化机会需要改变线格式,因此无法应用;现在我们在 OpenZL 中有了这样做的机会。此外,OpenZL 可以利用压缩技术的新进展,特别是 Marcin Żukowski 的 PivCo Huffman。这些优化结合在一起,使我们能够在可比压缩率下提供比 Zstandard 快 2 倍以上的解压速度。
模块化图设计:OpenZL 的模块化图设计允许我们替换后端熵压缩器,以最佳匹配正在压缩的数据。后端熵压缩器在压缩率、压缩速度和解压速度的权衡中扮演重要角色;OpenZL 的灵活性允许我们微调这种权衡。OpenZL 的训练器允许用户利用这种模块化构建 LZ 压缩器的帕累托前沿,为其数据提供广泛的最优权衡。
性能
OpenZL 目前提供的 LZ 压缩配置对应 Zstandard 级别 1 到 7,以及通过关闭后端熵压缩来与 LZ4 竞争的配置。我们预计将继续扩展支持的压缩配置,以覆盖 Zstandard 的整个压缩级别范围甚至更多。
在整个压缩级别范围内,OpenZL 的解压速度比 Zstandard 快 2 倍以上,比 LZ4 快最多 50%。
Silesia:解压速度 vs. 压缩率
详情
请注意,在较高压缩级别下,OpenZL 的压缩通常略差于 Zstandard。这主要是因为 OpenZL 目前不支持重复偏移。不过,OpenZL 的模块化设计将允许我们在开发该编解码器时插入重复偏移支持,并且只在需要时使用它。
训练
OpenZL 附带一个训练器,可自动构建和调优压缩器,以最佳匹配它们将要压缩的数据形态。我们添加了一个 LZ 训练器,它调优压缩搜索策略参数和后端熵压缩器,以提供压缩率、压缩速度和解压速度最优权衡的压缩器帕累托前沿。有关如何运行训练器的详细信息,请见下文。
在典型数据上,例如 silesia/reymont 或 silesia/nci,这通常比通用配置有小幅改进,并扩展了大小/速度权衡的范围。但在高度可压缩的数据上,例如 zstd.log(由 Zstandard 压缩产生的详细日志文件),它可以通过替换后端压缩图显著改善压缩。对于 zstd.log 中 OpenZL 提供 40 倍及以上压缩率的权衡点,训练器决定对 LZ 偏移运行 FieldLZ 编解码器(用于整数的 LZ),这大幅提高了压缩率。这在 Zstandard 这样的传统压缩器中是不可能的,但 OpenZL 基于图的模型使其变得自然。
silesia/reymont
silesia/nci
zstd.log
silesia/reymont
详情
如何使用
CLI
你可以通过选择lz配置文件从zliCLI 使用 LZ 引擎。例如,要在$SAMPLE_DIR目录中的数据上对压缩级别 1 和 -1 进行基准测试,可以运行:
zli benchmark--profilelz--level1$SAMPLE_DIRzli benchmark--profilelz--level=-1$SAMPLE_DIR为了为你的数据训练 LZ 压缩器的帕累托前沿,可以运行:
zli train--profilelz --pareto-frontier$SAMPLE_DIR--output$OUTPUT_DIR它将在$OUTPUT_DIR中生成一组压缩器,以及描述每个压缩器性能的benchmark.csv。
API
LZ 压缩器可以通过 API 使用,在 C 中使用ZL_GRAPH_LZ,在 C++ 中使用openzl::graphs::Lz。
亮点
LZ 引擎已从头重写以最大化性能,有许多优化值得讨论;不过,我们将在本文中选择两个重点介绍:我们开发的一种新颖的偏移编码方案,以及来自社区的一种新颖的 Huffman 编码布局。未来的文章将介绍 LZ 解码器的其余部分,并扩展此处总结的偏移编码方案。
偏移编码
LZ 解析的结果是 4 个输出数组:
- 字面量:无法用引用替换的字节
- 字面量长度:要发出多少字面量
- 匹配长度:匹配有多长
- 偏移:匹配向前回溯多远
要解码序列 i,LZ 解码器首先将literal_lengths[i]个字节从字面量缓冲区复制到输出缓冲区,然后从offsets[i]字节之前的位置复制match_lengths[i]个字节到输出缓冲区。
LZ 中的主要开销之一是偏移的编码和解码,既包括压缩大小,也包括解码速度。它们也是 LZ 解析中最棘手的编码部分,因为它们通常是 32 位整数,而字面量长度和匹配长度通常非常小,几乎总是能放进一个字节,偏移的取值范围则宽得多。
Zstandard 将偏移拆分为 2 的幂和余数,为每个偏移发出一个元组(2 的幂,余数),其中 2 的幂使用 FSE 编码,余数使用最少位数编码。OpenZL 使用一种新颖的方案,通过 V-最优直方图算法将偏移动态划分为 16 或 32 个桶,并为每个偏移发出一个元组(桶 ID,桶内位置),其中桶 ID 根据桶的数量使用 4 或 5 位进行位打包,桶内位置根据其落入桶的大小使用最少位数编码。这使 OpenZL 能够在完全不使用熵编解码器的情况下编码偏移,从而提供快 2 到 3.5 倍的偏移解码,而压缩率仅有少量损失。
PivCo Huffman
PivCo Huffman 是 Marcin Żukowski 提出的一种新 Huffman 布局,通过利用 SIMD 代码实现显著更快的解码速度。在相似的压缩速度下,它比 OpenZL 当前的 Huffman 实现提供快 2-3 倍的解压速度。OpenZL 的 v0.3.0 版本包含了 PivCo Huffman 的实现,并在 LZ 引擎中默认启用。
为了提供直观理解,下面包含论文中的一张图。传统 Huffman 按图像顶部所示布局比特。PivCo Huffman 在 Huffman 树的每个内部节点存储一个位图,然后自底向上重建原始数据,根据该位图合并两个子节点。完整细节请参阅论文。
PivCo Huffman 图
在所有其他解压速度优化之后,Huffman 是唯一尚未优化的编解码器,通常占 LZ 解压 CPU 的 50% 以上。因此,当 Marcin 发表论文时,我们很高兴在 OpenZL 中实现 PivCo。自我们实现以来,上游 PivCo Huffman 持续演进和改进,我们预计将在未来版本中引入这些改进,并将任何有意义的想法回馈给上游。
未来工作
虽然 LZ 引擎今天已经可以使用,但它仍在积极开发中,功能集每个版本都在扩展。OpenZL 的格式版本化允许我们安全地添加新功能,同时保留以旧格式版本编码和解码的能力。在未来的版本中,我们预计将:
- 扩展压缩级别支持,以覆盖 Zstandard 的整个压缩级别范围。
- 添加字典压缩支持,以改善小数据的压缩。
- 添加重复偏移支持,以改善某些场景下的压缩率。
- 扩展 LZ 训练器支持和搜索的后端压缩图集合。
请试用它,并将任何反馈或功能请求提交到我们的问题板!