跳到正文
原文
Simon Willison·· 10 小时前精选AI 评分70

SQLite扩展C与Rust性能对比

parse_number() as a SQLite extension: C vs Rust

AI 摘要

四个SQLite扩展用C和Rust实现相同的`parse_number()`行为,测试覆盖类型保留、解析规则和浮点精度,优化C实现每行16–19纳秒最快,约是Rust版本的两倍,远超SQL `replace()`

正文 · AI 翻译

研究 parse_number() 作为 SQLite 扩展:C 与 Rust — 四个 SQLite 扩展在 C 和 Rust 中实现了相同的 `parse_number()` 行为,测试覆盖了类型保持、解析规则和浮点精度。优化的 C 实现最快,每行 16–19 ns,比 Rust 版本快约两倍,远快于 SQL `replace()`。纯 C 在小数上较慢,因为它依赖 `strtod()`,而一个紧凑的快速路径缩小了这一差距;所有版本在 800 万次模糊测试中表现一致。

我正在遛狗时,好奇编写一个 SQLite C 扩展来添加一个 parse_number() 函数,将 -$1,234.56 或 '12.5%' 这样的字符串转换为可求和和排序的数值,会容易还是困难.

我启动了常规的 Claude 聊天(Opus 5.5) 并提示:

I'm thinking about a SQLite custom function 'parse_number(value)' that strips ',', '$', '£' and '%', handles a leading '-', and returns 'NULL' for anything it can’t parse

Explore the difference between building this as a SQLite extension in C v.s. in Rust - I want to compare performance and code complexity and size of the resulting.so(or whatever) file

这给了我一个坚实的基础——使用 Rusqlite 的 Rust 扩展是 321 KB,使用 sqlite-loadable-rs 的是 298 KB,而 C 扩展只有 14 KB。但 Rust 扩展更快!

原来是因为 Rust 中 C 的 strtod 的等效版本 "快两倍"。所以我提示:

Try writing your own C function for parsing text into a decimal number that catches up to or beats the Rust implementation

它做到了:

超过 200 万行每行的净成本,越低越好:

first C new 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

最后,我让它将原型改写为研究报告,以匹配 simonw/research 中的其他报告,提示如下:

Clone simonw/research from GitHub and turn your above investigation into a research report as seen in that repository - you can give me a zip file to download that contains your new folder

这是 生成的报告。

来源:Simon Willison · simonwillison.net

00