SQLite 확장으로 parse_number() 구현: C와 Rust 성능·크기 비교
parse_number() as a SQLite extension: C vs Rust
Simon Willison이 SQLite 커스텀 함수 parse_number()를 C 확장과 Rust 확장으로 각각 구현해 성능과 파일 크기를 비교했다. 처음 C 버전은 Rust보다 느렸지만, Claude에게 Clinger's fast path 기반 C 파싱 함수를 다시 작성하게 해 Rust 구현을 앞질렀다. 기사에 따르면 parse_number()는 '-$1,234.56'이나 '12.5%' 같은 문자열에서 ',', '$', '£', '%'를 제거하고 앞의 '-'를 처리해 합산·정렬 가능한 숫자로 바꾸며, 파싱할 수 없는 값에는 NULL을 반환한다. 컴파일 결과물은 Rust가 rusqlite 기반 321 KB, sqlite-loadable-rs 기반 298 KB였던 반면 C는 14 KB였다. 초기 C 구현은 행당 67 ns(혼합 데이터)로 Rust의 46 ns, 41 ns보다 느렸으나, Rust가 쓰는 strtod 대비 약 두 배 빠른 방식이 원인으로 확인됐다. 이후 작성된 새 C 구현은 혼합 데이터 19 ns, 정수 전용 16 ns, 소수 전용 18 ns를 기록해 Rust 구현들을 모든 항목에서 앞섰다. 기사는 200만 행 기준 행당 순비용(낮을수록 좋음)으로 결과를 제시했으며, 최종 결과물은 simonw/research 저장소 형식에 맞춘 연구 보고서와 zip 파일로 정리되었다.
rusqlite(321 KB)나 sqlite-loadable-rs(298 KB) 대신 14 KB짜리 C 확장으로 parse_number()를 구현하면 행당 19 ns 수준의 파싱 성능을 얻을 수 있다.
원문 출처
Simon Willison's Weblog