cd /news/developer-tools/parse-number-as-a-sqlite-extension-c… · home › topics › developer-tools › article
[ARTICLE · art-165750] src=simonwillison.net ↗ pub= topic=developer-tools verified=true sentiment=↑ positive

Parse_number() as a SQLite extension: C vs. Rust

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.

read2 min views7 publishedNov 9, 2026

8th November 2026

Research parse_number() as a SQLite extension: C vs Rust— 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.

I 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.

I fired up regular Claude chat (Opus 5.5) and prompted: 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

This gave me a solid starting point - the Rust extension was 321 KB (using Rusqlite) and 298 KB (using sqlite-loadable-rs), while the C extension was 14 KB. But the Rust extension was faster!

Turns out that's because the Rust equivalent of C's strtod is "twice as fast". So I prompted:

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

And it did:

Net cost per row over 2 million rows, lower is better:

first 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

Finally, I had it rewrite the prototype as a research report to match the others in simonw/research by prompting this:

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

Here's the resulting report.

Recent articles #

- [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
- [The U.S. Census Bureau and “Super Intelligence”](https://simonwillison.net/2026/Nov/2/census-bureau-super-intelligence/) - 2nd November 2026
- [The October inflection point for vibe game development](https://simonwillison.net/2026/Oct/28/vibe-game-development/) - 28th October 2026
- [Battle Drones - a vibe coded RTS with audio-based multiplayer](https://simonwillison.net/2026/Oct/20/battledrones/) - 20th October 2026
── more in #developer-tools 4 stories · sorted by recency
── more on @simon willison 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/parse-number-as-a-sq…] indexed:0 read:2min 2026-11-09 · —