{"slug": "parse-number-as-a-sqlite-extension-c-vs-rust", "title": "Parse_number() as a SQLite extension: C vs. Rust", "summary": "A research report published by Simon Willison on 8th November 2026 found that a hand-optimized C SQLite extension implementing parse_number() ran at 16–19 ns per row, roughly twice as fast as Rust versions built with Rusqlite (41–46 ns) and sqlite-loadable-rs (32–41 ns), despite the C extension's 14 KB binary versus 321 KB and 298 KB for the Rust builds. The optimized C fast path closed the gap left by plain C's reliance on strtod(), which made decimals-only parsing slower at 106 ns per row, and all four implementations matched across 8 million fuzz checks. Willison prompted Claude Opus 5.5 to build the extensions and rewrite the investigation as a report in the simonw/research repository.", "body_md": "8th November 2026\n\n[Research](https://simonwillison.net/elsewhere/research/)\n\n[parse_number() as a SQLite extension: C vs Rust](https://github.com/simonw/research/tree/main/sqlite-parse-number-c-vs-rust#readme)— Four SQLite extensions implement the same `parse_number()` behavior in C and Rust, with tests covering type preservation, parsing rules, and floating-point accuracy. The optimized C implementation was fastest at 16–19 ns per row, about twice as fast as the Rust versions and far faster than SQL `replace()`. Plain C was slower on decimals because it relied on `strtod()`, while a compact fast path closed that gap; all versions matched across 8 million fuzz checks.\n\nI was out walking the dog when I got curious about how easy/difficult it would be to write a SQLite C extension that adds a `parse_number()` function for turning strings like `-$1,234.56` or `'12.5%'` into numeric values that could be summed and sorted.\n\nI fired up regular Claude chat (Opus 5.5) [and prompted](https://claude.ai/share/7f18f157-6c96-4d49-a1d4-f02403e3b261):\n\n`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`\n\n`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`\n\nThis gave me a solid starting point - the Rust extension was 321 KB (using [Rusqlite](https://github.com/rusqlite/rusqlite)) and 298 KB (using [sqlite-loadable-rs](https://github.com/asg017/sqlite-loadable-rs)), while the C extension was 14 KB. But the Rust extension was faster!\n\nTurns out that's because the Rust equivalent of C's `strtod` is \"twice as fast\". So I prompted:\n\n`Try writing your own C function for parsing text into a decimal number that catches up to or beats the Rust implementation`\n\nAnd it did:\n\nNet cost per row over 2 million rows, lower is better:\n\nfirst C new C rusqlite sqlite-loadable Mixed data 67 ns **19 ns** 46 ns 41 ns Integers only 25 ns **16 ns** 36 ns 32 ns Decimals only 106 ns **18 ns** 55 ns 47 ns \n\nFinally, I had it rewrite the prototype as a research report to match the others in [simonw/research](https://github.com/simonw/research) by prompting this:\n\n`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`\n\nHere's [the resulting report](https://github.com/simonw/research/tree/main/sqlite-parse-number-c-vs-rust#readme).\n\n## Recent articles\n\n- [Qwen 3.8 27B on my laptop can interpret model weights, too](https://simonwillison.net/2026/Nov/3/qwen-can-interpret-model-weights/) - 3rd November 2026\n- [The U.S. Census Bureau and “Super Intelligence”](https://simonwillison.net/2026/Nov/2/census-bureau-super-intelligence/) - 2nd November 2026\n- [The October inflection point for vibe game development](https://simonwillison.net/2026/Oct/28/vibe-game-development/) - 28th October 2026\n- [Battle Drones - a vibe coded RTS with audio-based multiplayer](https://simonwillison.net/2026/Oct/20/battledrones/) - 20th October 2026", "url": "https://wpnews.pro/news/parse-number-as-a-sqlite-extension-c-vs-rust", "canonical_source": "https://simonwillison.net/2026/Nov/8/sqlite-parse-number-c-vs-rust/", "published_at": "2026-11-09 01:04:19+00:00", "updated_at": "2026-11-09 01:32:21.649185+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools"], "entities": ["Simon Willison", "SQLite", "Rust", "C", "Rusqlite", "sqlite-loadable-rs", "Claude Opus 5.5", "simonw/research"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/parse-number-as-a-sqlite-extension-c-vs-rust", "markdown": "https://wpnews.pro/news/parse-number-as-a-sqlite-extension-c-vs-rust.md", "text": "https://wpnews.pro/news/parse-number-as-a-sqlite-extension-c-vs-rust.txt", "jsonld": "https://wpnews.pro/news/parse-number-as-a-sqlite-extension-c-vs-rust.jsonld"}}