Rust in Everything
基于 pulldown-cmark 0.13.5

设计取舍

前五部分讲的是 pulldown-cmark 怎么建块树、怎么按需解析行内、字符串怎么借、事件怎么写成 HTML。这一部分只有一页,回头看那些代码背后的选择。README 给的目标是快(「a bare minimum of allocation and copying」)、安全(除了可选的 SIMD 没有 unsafe)、能给出源码位置、符合 CommonMark;每个取舍都落到具体的源码,说明换来了什么、放弃了什么,配本卷各页和本页自己的实测,和 comrak、markdown-rs 只对照测过的项。

  1. 设计取舍:事件流在 spec.txt 上 0.444 ms、674 KB、70 次分配;两遍是 CommonMark 逼的,第一个事件前要先建完整棵块树(一个没有链接定义和列表的子集 0.0003 ms 就能出第一个事件,pulldown-cmark 要 6 ms);扁平树和 CowStr 让分配几乎只剩树本身,代价是只增不删和事件绑着输入;扩展是运行时的 Options 位,本站七个选项慢 5%,Tag、Event 不是 non_exhaustive;默认原样输出 <script>,comrak、markdown-rs 默认都拦;dos-fuzzer 和一串下界与上限防平方,上限超了会静默改结果(一个 1000 字节的地址最多展开 100 次);SIMD 只在 x86_64,Rosetta 下没测出收益。
flowchart TB
  goal["快 安全 可定位 合规"] --> pull["事件流"]
  goal --> two["两遍"]
  goal --> flat["扁平树与借用"]
  goal --> opts["Options 位"]
  goal --> raw["不净化"]
  goal --> guard["上限与守卫"]
  goal --> simd["只在 x86_64 的 SIMD"]

这些取舍在实际项目里会变成具体的坑,报错原文和最小复现在 07 常见坑;本站怎么用事件流、怎么处理原样 HTML,见 08 在本站中。

💬 关联讨论

发起讨论
加载中...