ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

MongoDB 内置 zstd 库的 externalSequenceProducer 测试工具:块级序列生产者 API 实战指南

MongoDB 内置 zstd 库的 externalSequenceProducer 测试工具:块级序列生产者 API 实战指南 MongoDB 内置 zstd 库的 externalSequenceProducer 测试工具块级序列生产者 API 实战指南【免费下载链接】mongoThe MongoDB Database项目地址: https://gitcode.com/GitHub_Trending/mo/mongo本文围绕 MongoDB 源码树中随 zstandard 库一起引入的externalSequenceProducer贡献组件README展开它是 zstd Block-Level Sequence Producer API 的官方测试工具通过一次压缩—解压—比对的往返round-trip验证演示了如何把用户自定义的序列解析函数注册进 zstd 压缩上下文。读完全文你将掌握该 API 的注册方式、参数含义、序列合法性约束与已知限制并能自行替换样例实现、构建并运行这个往返测试程序。一、externalSequenceProducer 是什么按照 README 的定义externalSequenceProducer是Block-Level Sequence Producer API 的测试工具用于演示如何借助该 API 执行一次简单的往返测试目录内自带的sequence_producer.c提供了一个样例序列生产者sample sequence producer使用者可以随时换成自己的实现样例实现执行的是基于 1KB 哈希表的 LZ 解析基于字典的解析目前不受支持dictionary-based parsing is not currently supported。组件目录结构非常精简共 5 个文件文件作用README.md工具说明与命令行用法main.c往返测试驱动注册生产者、压缩、解压、校验sequence_producer.c样例序列生产者1KB 哈希表 LZ 解析sequence_producer.h生产者函数签名声明Makefile构建脚本链接静态库libzstd.a二、构建与命令行用法2.1 构建Makefile 的构建流程是LIBZSTD $(LIBDIR)/libzstd.a # LIBDIR ../../lib CFLAGS ? -O3 CFLAGS -stdgnu99 externalSequenceProducer: sequence_producer.c main.c $(LIBZSTD) $(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $ $(LIBZSTD): $(MAKE) -C $(LIBDIR) libzstd.a CFLAGS$(CFLAGS)即如果 zstd 的lib/目录下还没有静态库libzstd.aMakefile 会先执行make -C ../../lib libzstd.a构建它再把sequence_producer.c与main.c一并编译链接头文件搜索路径通过-I../../lib -I../../lib/compress -I../../lib/common提供其中compress/与common/下的内部头文件是样例生产者实现所必需的。在src/third_party/zstandard/zstd/contrib/externalSequenceProducer/目录下执行make即可得到可执行文件。2.2 运行README 给出的唯一命令行形式是externalSequenceProducer filenamemain.c中的入口逻辑与之一致参数个数必须恰好为 2否则打印Usage: externalSequenceProducer file并返回 1。程序随后读取整个文件、压缩、解压并用memcmp比对原始数据与解压结果成功时输出Compression and decompression were successful! Original size: 原始字节数 Compressed size: 压缩后字节数若校验失败程序会定位并打印第一个不一致的字节下标以便快速定位解析错误。三、核心 API把序列生产者注册进 zstd3.1 注册调用main.c 中最关键的几行代码源码注释原话是ZSTD_CCtx* const zc ZSTD_createCCtx(); int simpleSequenceProducerState 0xdeadbeef; // 用户自管的状态指针所指对象 ZSTD_registerSequenceProducer( zc, simpleSequenceProducerState, simpleSequenceProducer ); { size_t const res ZSTD_CCtx_setParameter(zc, ZSTD_c_enableSeqProducerFallback, 1); CHECK(res); }其中CHECK(res)宏main.c统一用ZSTD_isError/ZSTD_getErrorName检查 zstd 返回值出错即打印错误名并返回 1是 zstd C API 的典型错误处理方式。API 声明位于 zstd.h#define ZSTD_SEQUENCE_PRODUCER_ERROR ((size_t)(-1)) typedef size_t ZSTD_sequenceProducer_F ( void* sequenceProducerState, ZSTD_Sequence* outSeqs, size_t outSeqsCapacity, const void* src, size_t srcSize, const void* dict, size_t dictSize, int compressionLevel, size_t windowSize ); ZSTDLIB_STATIC_API void ZSTD_registerSequenceProducer( ZSTD_CCtx* cctx, void* sequenceProducerState, ZSTD_sequenceProducer_F* sequenceProducer );3.2 每个参数的语义根据 zstd.h 中 API 文档的逐条说明zstd按块block调用用户函数传入参数含义与约束sequenceProducerState用户自管的序列生产者状态指针zstd 不负责其初始化与销毁outSeqs,outSeqsCapacity输出序列缓冲区outSeqsCapacity保证 ≥ZSTD_sequenceBound(srcSize)底层内存由 CCtx 管理src,srcSize待解析输入srcSize保证 ≤ZSTD_BLOCKSIZE_MAX128KBdict,dictSize历史缓冲。当前 zstd总是传dictSize 0未来会变化compressionLevel用户设置的压缩级别供生产者自行决定速度/比率取舍注意它不反映高级 API 设置的其他参数windowSize外部序列允许的最大 offset存在字典时 offset 有时可超出该窗口细节见 zstd 压缩格式文档返回值为写入outSeqs的序列个数返回值大于outSeqsCapacity会被当作错误码可便捷使用ZSTD_SEQUENCE_PRODUCER_ERROR宏。当srcSize非零时返回值必须非零。3.3 注册行为与生效范围注册是粘性的sticky一经设置在用户显式重置压缩参数之前一直保留跨多次压缩生效该设置属于advanced API只有尊重高级参数的压缩接口如ZSTD_compress2、compressStream2才会生效compressCCtx等老接口会忽略外部序列生产者传NULL函数指针即可清除注册同时解除下述所有限制测试工具中sequenceProducerState故意初始化成0xdeadbeefmain.c样例生产者并未使用它sequence_producer.c中直接(void)sequenceProducerState仅用于演示状态指针由用户初始化、由用户销毁这一约定。3.4 内部实现落点ZSTD_registerSequenceProducer的实现位于 zstd_compress.c。从源码结构看它会把用户函数指针存入CCtx参数结构体并置位一个仅供内部使用的标志位useSequenceProducer见 zstd_compress_internal.h 中的注释Users cant set this externally. It is set internally in ZSTD_registerSequenceProducer().压缩路径据此分流到外部序列解析逻辑。四、样例序列生产者1KB 哈希表的 LZ 解析sequence_producer.c 是整个演示的教学核心它展示了一个最小的合法 LZ 解析长什么样#define HSIZE 1024 static U32 const HLOG 10; static U32 const MLS 4; static U32 const BADIDX 0xffffffff; size_t simpleSequenceProducer( void* sequenceProducerState, ZSTD_Sequence* outSeqs, size_t outSeqsCapacity, const void* src, size_t srcSize, const void* dict, size_t dictSize, int compressionLevel, size_t windowSize)算法主循环sequence_producer.c以 4 字节MLS 4即 minimum literal size为步长扫描输入用ZSTD_hashPtr(ip, HLOG, MLS)对当前 4 字节取哈希在hashTable[1024]中查最近出现过该前缀的偏移matchIndex然后把当前位置写入哈希表命中且ZSTD_count(ip, match, iend)得到的匹配长度 ≥ZSTD_MINMATCH_MIN时产出序列{offset, litLen, matchLen, 0}关键检查if (offset windowSize)才真正写入outSeqs并跳进matchLen字节——源码注释强调 its crucial to stay within the window size!。超过窗口的匹配被丢弃解析退化为逐字节前移ip循环结束后追加收尾序列{0, 剩余字面长度, 0, 0}offset 为 0、matchLen 为 0、字面长度等于iend - anchor。这个收尾序列恰好满足 API 规定的合法解析条件见下节末序列matchLength 0时offset必须为 0。注意样例对dict、dictSize、outSeqsCapacity、compressionLevel全部做了(void)忽略处理——这正对应 README 中基于字典的解析目前不受支持的说明。五、序列合法性规则与错误回退机制5.1 合法解析valid parse的判据zstd.h 明确规定若生产者未返回错误码则写入的序列必须是src缓冲的合法解析否则可能导致数据损坏。合法解析需同时满足所有序列的matchLength literalLength之和必须等于srcSize除末序列外每个序列的matchLength ZSTD_MINMATCH_MIN末序列matchLength要么 ≥ZSTD_MINMATCH_MIN要么为 0所有 offset 必须遵守windowSize参数细节见 zstd 压缩格式文档若末序列matchLength 0则其offset也必须为 0。zstd 只在ZSTD_c_validateSequences参数开启时校验上述条件不满足则压缩失败因为序列校验有性能开销——生产路径上默认信任用户实现。5.2 ZSTD_c_enableSeqProducerFallback错误时的兜底策略测试工具在main.c里显式打开了这个实验性参数ZSTD_c_experimentalParam17。zstd.h 对其的定义取值 0默认或 1控制当外部序列生产者返回错误码时zstd 是否回退到内部序列生产者回退是**逐块block-by-block**的只有外部生产者报错的那些块才由内部生产者解析回退解析同样遵守当前已设置的其他 cParam如压缩级别与正常压缩行为一致。换言之不开该参数时外部生产者报错 → 整个压缩操作失败打开后单个块的解析失败可被内部实现兜住整个压缩仍可成功。main.c 选择打开它使样例即使遇到不可解析的块也能完成往返演示。六、当前 API 的三项限制zstd.h 的 LIMITATIONS 章节明确列出了 Block-Level Sequence Producer API 目前不能与之共存的场景使用方必须知晓不支持ZSTD_c_enableLongDistanceMatching若该参数处于启用状态而外部生产者已注册压缩会直接失败。由于部分配置下 LDM 会自动开启例如从源码注释看ZSTD_c_windowLog 128MB时默认关闭 LDM但此行为可能变化注册外部生产者时必须显式将ZSTD_c_enableLongDistanceMatching设为ZSTD_ps_disable来规避不支持历史缓冲history bufferzstd 目前总是传dictSize 0导致——字典不受支持引用字典不会让压缩失败但不会产生任何效果流式历史不受支持所有高级压缩 API含流式 API都能与外部生产者配合但每个块都被当作独立片段处理无法利用前序块的历史单次压缩内不支持多线程ZSTD_c_nbWorkers 0且注册了外部生产者时压缩会直接失败。跨压缩的多线程没问题每线程一个 CCtx 即可。API 文档同时表示这三项限制长期计划全部解除没有技术障碍纯粹是工程投入问题。七、在仓库中进一步验证测试与模糊测试除 contrib 下这个演示工具外zstd 库自身的测试基础设施也在用同一套 API可作为交叉佐证路径相对于 zstd 子树本文按仓库根目录给出tests/zstreamtest.c在流式压缩场景中注册/清除外部序列生产者并在不同ZSTD_c_enableSeqProducerFallback取值下运行压缩——这正是main.c演示行为的完整版测试其中ZSTD_registerSequenceProducer(zc, NULL, NULL)被用于清除外部 matchfindertests/fuzz/fuzz_third_party_seq_prod.h 与 tests/fuzz/zstd_helpers.c把ZSTD_registerSequenceProducer纳入模糊测试辅助函数并对ZSTD_c_enableSeqProducerFallback做 0/1 随机化setRand(...)以覆盖回退路径。从源码结构看ZSTD_registerSequenceProducer与ZSTD_c_enableSeqProducerFallback在 zstd_compress.c 的参数解析表中出现于多处取值校验与参数拷贝分支说明该 API 与 CCtx 参数体系是深度集成的而非外挂机制。八、小结externalSequenceProducer虽然只有 5 个文件却完整串起了 zstd 块级序列生产者 API 的使用闭环注册ZSTD_createCCtx()后调用ZSTD_registerSequenceProducer(ccctx, state, producerFn)state 由用户初始化与销毁NULL指针用于清除实现用户函数接收每块一个的输入≤ 128KB向 CCtx 提供的输出缓冲写回序列返回序列数样例 sequence_producer.c 用 1024 项哈希表、4 字节最小匹配、窗口约束与零 offset 收尾序列给出了最小合法解析的范式容错用ZSTD_c_enableSeqProducerFallback决定生产者报错时整次失败还是逐块回退验证make ./externalSequenceProducer file即可完成一次可复现的压缩—解压—逐字节比对往返测试。需要强调的是适用边界该工具位于 MongoDB 源码树中 zstandard 的contrib/目录属于 zstd 上游贡献组件而非 MongoDB 服务代码仅在构建/研究 MongoDB 所集成的 zstd 压缩栈时才有意义且受第六节所列限制约束无字典、无历史、单线程块解析、禁 LDM生产级自定义序列生产者落地前应先对照这些约束评估可行性。【免费下载链接】mongoThe MongoDB Database项目地址: https://gitcode.com/GitHub_Trending/mo/mongo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表