Newshot
Account

将 parse_number() 实现为 SQLite 扩展:C 与 Rust 对比

AI summary

作者研究把 parse_number() 写成 SQLite 扩展,用于将 -$1,234.56 或 '12.5%' 这类字符串转成可求和、可排序的数值,并比较 C 与 Rust 实现的性能、代码复杂度与产物体积。结果 Rust 扩展为 321 KB(用 Rusqlite)和 298 KB(用 sqlite-loadable-rs),C 扩展仅 14 KB,但 Rust 版本更快,原因是 Rust 中对应 C 的 strtod 的实现“快一倍”。

Translation(model translation, not the source's own text)

parse_number() 作为 SQLite 扩展:C 与 Rust

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

我打开普通的 Claude 聊天(Opus 5.5),输入了提示:

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

我正在考虑一个 SQLite 自定义函数 'parse_number(value)',它会去掉 ','、'$'、'£' 和 '%',处理前导 '-',并对任何无法解析的内容返回 'NULL'

探索用 C 与用 Rust 将其构建为 SQLite 扩展的差异——我想比较性能、代码复杂度以及生成的 .so(或类似)文件的大小

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

原来这是因为 C 的 strtod 在 Rust 中的对应实现“快两倍”。于是我又输入了提示:

试着编写你自己的 C 函数,将文本解析为十进制数,使其追平或超过 Rust 实现

它做到了,使用的是“Clinger's fast path”:

在 200 万行上每行的净开销,越低越好:初版 C 新版 C rusqlite sqlite-loadable 混合数据 67 ns 19 ns 46 ns 41 ns 仅整数 25 ns 16 ns 36 ns 32 ns 仅小数 106 ns 18 ns 55 ns 47 ns

在 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 文件,其中包含你的新文件夹

这是最终得到的报告。

The translation is machine-generated and individual terms may be off. Nothing is rewritten or cut; the original is authoritative.

Published by Simon Willison
This site only summarises and aggregates; copyright stays with the original author. Headlines and summaries follow the source — where they differ, the original wins.
Read the original ↗