2026-11-08 · ← ニュース
最適化したC版はparse_number()を19 nsに短縮。Rustが勝ったのは初戦だけだった
Simon Willisonは、数値文字列を解析する4つのSQLite拡張を比較した。素朴なC版にはRustが勝ったが、約30行の最適化でC版は1行あたり19.2 nsまで短縮され、言語ベンチマークが実際にはparserの選択を測っている場合があることを示した。
画像を読み込めませんでした。
Simon WillisonはClaude Opus 5.5を使い、-$1,234.56のような文字列を数値に変換するSQLite関数parse_number()を4種類作成した。この実験の価値は、最初の意外な結果で止まらず、その原因まで切り分けた点にある。
Rustは素朴なC版に勝ったが、汎用parserを外すと順位が逆転した
比較したのはRust版が2つ、C版が2つ。混合データでは、素朴なC版が1行あたり67.3 ns、Rust版が40.5から45.9 nsだった。小数だけでは差がさらに広がり、C版の106.3 nsに対してRust版は46.5から54.5 nsだった。
原因は言語全体の性能ではない。C版は小数を汎用関数strtod()に渡し、Rust版はparser内の高速な経路を使っていた。一般的な値を処理する約30行を追加すると、最適化したC版は混合データで19.2 ns、整数で15.8 ns、小数で17.5 nsまで短縮した。
小さな関数が抽象化のコストと手作業の代償を映した
C拡張は14 408 Bだった。Rust版は標準ライブラリと補助コードを含むため、298 464 Bと320 864 Bになった。一方、最適化したC版は104行のコードに加え、bufferの手動管理、overflow確認、浮動小数点計算への注意が必要だった。
Rust版は短く、安全に書きやすい。開発者が選ぶべき軸は具体的だ。頻繁に呼ばれる小さな関数なら、Cでlatencyとbinary sizeを削れる可能性がある。ただし、複雑なコードと不具合の余地が増える。1 nsを削る価値と、保守する人の時間のどちらが重いかで選択は変わる。
これは限定的なmicrobenchmarkであり、言語全体の決着ではない
測定環境は2 vCPUのLinux x86-64マシン1台で、対象は200万行だった。各数値は15回の実行で最速だった値から、基準となるtable scanを差し引いている。関数のコストは分離しやすいが、別のC library、別のarchitecture、database以外の処理を含むapplicationで同じ結果になるとは限らない。
研究report自体もLLMの支援で作られた。信頼の根拠は文章の出自ではなく、公開されたcode、40件の手書きtest、差異が見つからなかった800万回のfuzz比較にある。それでも、別のマシンでの再現は、1つの表から導く強い断定より価値が高い。
別環境での再現が19.2 nsの強さを決める
次に欲しいのは、macOS、ARM、異なる標準library実装で同じbenchmarkを走らせた結果だ。Rust版2つからVec allocationを外せば、言語のコストとlibrary wrapperのコストも分けやすくなる。
実運用のimport dataでは、不正な値の割合、文字列の長さ、strtod()への遅いfallbackが動く頻度も効いてくる。benchmark用に整えられていないdataに触れたときも19.2 nsを保てるかが、最後の確認になる。
Lilithの判定
最初のC版にはRustが先着したが、200万行では最適化したC版が背中を見せた。これほど小さな関数では、言語の旗より実際に測っているparserが勝敗を決める。