AI 学习经验
用 Claude 写 SQLite 扩展:同一个 parse_number(),C 和 Rust 差在哪
Simon Willison 遛狗时想到给 SQLite 加一个 parse_number() 函数,把 '-$1,234.56'、'12.5%' 这类字符串转成可求和排序的数值。他用 Claude 对话依次探索 C 和 Rust 两种实现,对比性能、代码量和产物体积,最后让 AI 把整个过程整理成研究报告。
今天就能做
- 给 SQLite 写自定义函数时,C 扩展体积小得多(14 KB vs 约 300 KB),但性能要自己写解析逻辑才能发挥出来
- 遇到 AI 给出的性能意外结果,可以直接让它针对瓶颈重写,一轮对话就能把 106 ns 优化到 18 ns
- 用 fuzz 测试对比多个实现的输出一致性,是验证 AI 生成代码正确性的低成本手段
起点:一次对话拿到两个原型
- 目标函数 parse_number(value):去掉逗号、$、£、%,处理负号,解析失败返回 NULL
- Claude(Opus 5.5)一次就给出可用的 Rust 和 C 版本
- 产物体积差距明显:Rust 用 Rusqlite 是 321 KB,sqlite-loadable-rs 是 298 KB,C 只有 14 KB
意外结果:Rust 反而更快
- 初步基准测试中 Rust 版本跑赢了 C 版本
- 原因是 Rust 里对应 C strtod 的解析实现快了约一倍
- 于是追加提示词:让 Claude 自己写一个能追平或超过 Rust 的 C 解析函数
优化后的性能数据
- 在 200 万行上测每行净耗时:混合数据从 67 ns 降到 19 ns,Rusqlite 46 ns,sqlite-loadable 41 ns
- 纯整数场景:新 C 版 16 ns,Rust 两版分别为 36 ns 和 32 ns
- 纯小数场景差距最大:初版 C 106 ns,优化后 18 ns,Rust 为 55 ns 和 47 ns
- 优化 C 版整体比 Rust 快约一倍,远快于用 SQL replace() 拼接的做法
正确性验证与产出
- 四个实现(两个 C、两个 Rust)在 800 万次 fuzz 检查中结果完全一致
- 关键优化是给小数解析加了一条紧凑的快速路径,绕开 strtod 的开销
- 最后让 Claude 克隆 simonw/research 仓库,把调查过程改写成一份研究报告打包下载
值得借鉴的工作方式
- 整个项目由三段递进提示词完成:先探索对比,再针对性优化,最后整理成文
- 让 AI 对比自己写的两个版本,比单看一个实现更容易发现性能盲点
- 把探索过程沉淀为可复用的研究报告,而不是散落在聊天记录里
原文:Research: parse_number() as a SQLite extension: C vs Rust
来源:Simon Willison
查看原文本文由 AI 阅读原文后整理,未经人工逐字核对,内容以原文为准。
登录后可以点赞、查看和发表评论