Heidi Labs
Simon WillisonAI 权威大佬文章约 3 分钟1,215 字

把 parse_number() 写成 SQLite 扩展:C 与 Rust

Simon Willison 的博客

通讯

2026 年 11 月 8 日

研究

把 parse_number() 写成 SQLite 扩展:C 与 Rust —— 四个 SQLite 扩展分别用 C 和 Rust 实现了相同的 parse_number() 行为,测试覆盖类型保持、解析规则和浮点精度。优化后的 C 实现最快,每行 16–19 纳秒,约为 Rust 版本的两倍,也远快于 SQL 的 replace()。普通 C 实现在小数上较慢,因为它依赖 strtod();一条紧凑的快速路径弥补了这一差距;所有版本在 800 万次模糊测试(fuzz checks)中结果一致。

我遛狗时好奇:写一个 SQLite C 扩展有多容易、多困难?这个扩展要添加 parse_number() 函数,把 -$1,234.56 或 '12.5%' 这样的字符串转换成可求和、可排序的数值。

我打开常规的 Claude 聊天(Opus 5.5),提示道:

我在考虑实现一个 SQLite 自定义函数 'parse_number(value)',它会去掉 ','、'$'、'£' 和 '%',处理前导 '-',对无法解析的内容返回 'NULL' 探索把它构建成 C 版 SQLite 扩展与 Rust 版 SQLite 扩展的区别——我想比较性能、代码复杂度以及生成的 .so(或类似文件)的大小

这给了我一个可靠的起点——Rust 扩展是 321 KB(使用 Rusqlite)和 298 KB(使用 sqlite-loadable-rs),而 C 扩展是 14 KB。但 Rust 扩展更快!

原来,这是因为 Rust 中与 C 的 strtod 等价的实现“快两倍”。于是我又提示:

试着写一个你自己的 C 函数,把文本解析成十进制数,追上或超过 Rust 实现

它做到了:

超过 200 万行的每行净开销,越低越好:

最初的 C新的 Crusqlitesqlite-loadable
混合数据67 ns19 ns46 ns41 ns
仅整数25 ns16 ns36 ns32 ns
仅小数106 ns18 ns55 ns47 ns

最后,我让它把原型改写成研究报告,以与其他 simonw/research 中的报告保持一致,提示如下:

从 GitHub 克隆 simonw/research,把你上面的调查整理成该仓库中所见的那种研究报告——你可以给我一个 zip 文件下载,里面包含你的新文件夹

结果报告在这里。

发布于 2026 年 11 月 8 日晚上 10:26

近期文章#

  • 我笔记本上的 Qwen 3.8 27B 也能解读模型权重 - 2026 年 11 月 3 日
  • 美国人口普查局与“超级智能” - 2026 年 11 月 2 日
  • 氛围游戏开发的十月拐点 - 2026 年 10 月 28 日
  • Battle Drones——一款基于音频多人的氛围编程 RTS - 2026 年 10 月 20 日

这是 Simon Willison 于 2026 年 11 月 8 日发布的研究随笔(beat)。

标签:c(55)、research(12)、sqlite(490)、rust(116)、claude(324)