Carta:用Rust重写Pandoc,快45倍、体积小20倍

一次面向性能的文档转换器重构
文档转换是技术写作、学术出版和内容工程中的基础需求,而 Pandoc 一直是这个领域事实上的标准。它由加州大学伯克利分校哲学系教授 John MacFarlane(jgm)于2006年创建,凝聚了作者数十年在文档处理和函数式编程领域的经验,能够在 Markdown、DOCX、LaTeX、HTML 等数十种格式之间自由转换。然而,强大也意味着体积和运行开销的代价。
近日,一位开发者 mfkrause 在 Reddit 上发布了他的新项目 Carta——一个用 Rust 重新实现的 Pandoc。它的目标非常明确:在保留 Pandoc 核心工作方式的前提下,做到更小、更快。据作者介绍,Carta 编译后的二进制文件体积约为 Pandoc 的 1/20,转换速度最高可达 45 倍。

为什么要用Rust重写Pandoc
作者坦言,他对 Pandoc 本身评价极高,但长期以来困扰他的有两个具体问题。
二进制体积臃肿
Pandoc 在 Apple Silicon 平台上的构建产物约为 180 MB。对于一个命令行文档转换工具来说,这个体积相当可观,尤其在需要打包进容器镜像、CI/CD 流水线或嵌入到其他应用时,会带来明显的分发和存储负担。Carta 将这一数字压缩到约 20 分之一,也就是接近 9 MB 的量级。
体积差异的核心原因在于底层语言运行时的差异。Pandoc 使用 Haskell 编写,其编译器 GHC(Glasgow Haskell Compiler)在生成可执行文件时会将运行时系统(RTS)静态链接进二进制文件中。这个运行时包含垃圾回收器、轻量级线程调度器、异常处理机制等组件,即使程序本身并不需要并发功能,这些基础设施也会占据可观的空间。此外,Haskell 丰富的标准库和 Pandoc 依赖的大量第三方包在静态链接模式下也会增加最终产物的体积。相比之下,Rust 编译产物不包含 GC 运行时,标准库体积精简,且 LLVM 后端的链接时优化(LTO)可以有效剔除未使用的代码。
文档转换速度
Pandoc 的运行速度在单文档场景下尚可接受,但当需要批量转换大量文档时,性能瓶颈就会显现。Carta 借助 Rust 的零成本抽象和高效内存管理,实现了最高 45 倍的速度提升。这对于需要处理数千份文档的自动化场景(如静态站点生成、文档归档批处理)尤为关键。
Rust 的「零成本抽象」(Zero-Cost Abstractions)意味着开发者使用的高级抽象——泛型、迭代器组合、模式匹配等——在编译后不会产生比手写底层代码更多的运行时开销。Rust 编译器通过单态化(Monomorphization)将泛型代码展开为具体类型的专用版本,消除动态分派的成本。同时,Rust 的所有权系统和借用检查器在编译期即完成内存安全验证,无需垃圾回收器在运行时追踪对象生命周期。这意味着程序启动即可进入工作状态,没有 GC 暂停(stop-the-world pause),内存的分配和释放时机完全确定。对于文档转换这类需要频繁创建和销毁 AST 节点的场景,这种确定性内存管理带来的性能优势尤为显著。
有意思的是,Pandoc 使用 Haskell 编写,其运行时和 GC 机制在一定程度上影响了启动速度与内存占用。Haskell 的 GHC 运行时采用分代垃圾回收策略,对于长时间运行的服务而言表现优异,但对于「启动-处理-退出」的短生命周期命令行工具来说,运行时初始化和 GC 的开销占总执行时间的比例会被放大。当批量转换数千份文件时,每次调用都重复支付这笔启动成本,累积效应相当可观。而 Rust 的无 GC、编译期确定性使得 Carta 在这两个维度上天然占优。这也是近年来大量基础工具用 Rust 重写命令行工具趋势的又一例证。
Carta的架构设计:与Pandoc一脉相承
Carta 在底层的工作原理与 Pandoc 高度相似,这也是它能保持兼容性的关键。
其核心流程是:解析器(reader) 将输入文档解析为一个内部抽象语法树(AST),随后 写入器(writer) 将这个 AST 输出为目标格式。这种解耦设计带来了组合式的转换能力——理论上支持的转换总数等于 reader_formats × writer_formats,即任意支持的输入格式都可以转换到任意支持的输出格式。
这种「中间表示」(Intermediate Representation, IR)的设计思想源自编译器理论。在经典的编译器架构中,前端将源代码解析为 IR,后端将 IR 翻译为目标代码。这一分层设计的核心优势在于解决了「M×N 问题」:如果有 M 种输入格式和 N 种输出格式,直接两两实现需要 M×N 个转换器;而引入中间表示后,只需 M 个 reader 和 N 个 writer,总工作量降为 M+N。LLVM 项目就是这一思想最成功的工业级实践——它定义了 LLVM IR 作为中间语言,使得任何新语言只需实现一个前端即可获得所有后端平台的支持。Pandoc 将这一编译器设计哲学引入文档转换领域,定义了一套丰富的文档 AST 类型(包括段落、标题、列表、表格、代码块、引用、元数据等节点类型),使得格式之间的语义信息能够最大程度地保留。
Carta 沿用同样的哲学,意味着它未来扩展新格式时,只需增加对应的 reader 或 writer,而无需为每一对格式单独实现转换逻辑。
已实现的功能与Pandoc兼容性
目前 Carta 已经覆盖了最常用的格式和特性:
- Markdown 家族:多种 Markdown 方言的读写
- DOCX:Word 文档转换
- TeX / LaTeX:学术写作常用格式
- 语法高亮:代码块的着色处理
- JSON 过滤器:与 Pandoc 完全兼容,现有的 Pandoc filter 生态可以直接复用
- Standalone 模式:生成完整独立文档而非片段
其中 JSON filter 的完全兼容 是一个相当重要的设计决策。Pandoc 的 filter 机制是其生态系统中最强大的扩展能力之一,其工作原理体现了 Unix 管道哲学:Pandoc 将文档解析为 AST 后,以 JSON 格式序列化并通过标准输入(stdin)传递给外部 filter 程序,filter 对 JSON 形式的 AST 进行修改后通过标准输出(stdout)返回,Pandoc 再将修改后的 AST 渲染为目标格式。由于 filter 是独立进程,可以用任何编程语言实现——Python 社区的 panflute 和 pandocfilters 库就是最常用的 filter 开发框架。典型的 filter 用途包括:自动编号图表和公式、将 LaTeX 公式渲染为图片、替换自定义宏、插入交叉引用等。
Carta 保持这一兼容性,意味着已有的整个 filter 工具链可以无缝迁移,这大大降低了从 Pandoc 切换的门槛。
尚未支持的部分
作为一个仍在早期阶段的项目,Carta 也明确列出了当前的缺失功能:
- PDF 输出:Pandoc 本身并不直接生成 PDF,而是先生成 LaTeX 源文件,再调用 pdflatex、xelatex 或 lualatex 等 TeX 引擎进行排版编译。另一条路径是通过 HTML 中间格式调用 wkhtmltopdf 或 Prince 等工具进行渲染。无论哪条路径都涉及复杂的外部依赖管理、模板系统、字体处理和排版引擎集成,实现复杂度较高。
- Lua filters:Lua filter 是 Pandoc 2.0 引入的一项重要改进。与 JSON filter 需要启动外部进程不同,Lua filter 在 Pandoc 进程内部运行,通过内嵌的 Lua 5.4 解释器直接操作 AST 对象,避免了 JSON 序列化/反序列化和进程间通信的开销,性能显著优于 JSON filter。许多现代 Pandoc 工作流(如学术论文模板系统、技术文档生成管线)已经深度依赖 Lua filter。对 Carta 而言,实现 Lua filter 意味着需要集成一个 Lua 运行时并实现完整的 AST 绑定 API,这是一项不小的工程量。
这两项恰恰是 Pandoc 高级用户依赖较多的功能。因此在现阶段,Carta 更适合作为高频、轻量、批量转换场景下的替代品,而非全面取代 Pandoc。作者也在项目中提供了完整的功能对照表,供用户判断是否符合自己的需求。
开源许可与生态定位
Carta 采用 MIT 或 Apache-2.0 双许可,这是 Rust 社区的标准做法,对商业与开源使用都极为友好。项目已托管在 GitHub(mfkrause/carta),作者也在积极征求社区反馈。
从定位来看,Carta 不太可能在短期内取代功能全面的 Pandoc,但它填补了一个真实存在的需求空白:在对体积和速度敏感的环境下运行文档转换。CI 流水线、边缘计算、桌面应用嵌入、以及需要批量处理的内容工程,都是它潜在的用武之地。
结语
Carta 是「用 Rust 重写经典工具」这一趋势的又一个典型案例。近年来,Rust 社区涌现了大量此类项目:ripgrep(替代 grep,搜索速度通常快 2-10 倍)、fd(替代 find)、bat(替代 cat,内置语法高亮)、exa/eza(替代 ls)、zoxide(替代 cd)、delta(替代 diff)等。在更大型的基础设施层面,这一趋势也延伸到了 JavaScript 工具链领域——SWC(替代 Babel)、Turbopack(替代 Webpack)、Biome(替代 ESLint + Prettier),以及 Python 包管理领域的 uv(替代 pip/poetry),都是用 Rust 重写传统工具链并获得数量级性能提升的成功案例。这些项目共享几个共同特征:编译为无依赖的静态二进制文件便于分发、启动速度极快、内存占用可控、跨平台支持良好。
Carta 没有试图在功能上超越 Pandoc,而是选择了一个清晰的差异化路径——通过更现代的语言实现,在性能和分发成本上做出数量级的改进,同时尽可能保持与原有生态的兼容。
对于追求极致效率、且当前需求落在已支持格式范围内的开发者来说,Carta 值得一试。而随着 PDF 输出和 Lua filter 等功能的逐步补齐,它有望成为文档转换领域一个真正有竞争力的轻量级选择。
相关推荐

roastme.gg:花钱让AI公开吐槽你,这个反常识产品如何设计病毒传播
深度解析roastme.gg的产品设计逻辑:用户付费1到1000美元让Claude公开吐槽自己,通过排行榜和社交卡片实现病毒传播。探讨AI娱乐产品的商业模式与情绪价值变现路径。

TruIntel评测:监测品牌在AI搜索中可见度的分析工具
TruIntel是一款为AI搜索时代打造的品牌可见度分析工具,可追踪品牌在ChatGPT、Gemini、Perplexity等AI回答中的引用情况。本文深度解析其功能、GEO生成式引擎优化趋势及实际应用价值。

新奥尔良用AI分流911报警电话:智能调度如何改变应急响应
新奥尔良市部署AI系统对积压的911报警电话进行智能分流,通过语音识别和情绪分析快速识别高危事件。本文深入分析AI应急调度的运作机制、潜在风险及对公共安全领域的深远影响。