DEV Community

Cover image for SQLite 数字解析扩展:C 与 Rust 的体积和性能对比
arthur
arthur

Posted on

SQLite 数字解析扩展:C 与 Rust 的体积和性能对比

写好标智库

为 SQLite 增加数字清理与解析能力

当数据以 -$1,234.56、12.5% 这样的字符串保存时,直接求和或按数值排序并不方便。一种解决方式是为 SQLite 增加自定义函数 parse_number(value),先清理格式字符,再解析数值。

这次原型实验采用以下规则:

  • 移除逗号、美元符号、英镑符号和百分号。
  • 处理开头的负号。
  • 将能够解析的内容转换为数值,无法解析时返回 NULL。

移除百分号不等于除以 100。 按照这里的规则,12.5% 清理后对应的是 12.5,而不是 0.125。实现此类函数时,需要先明确业务所需的是字符清理还是百分比换算。

实验借助 Claude 生成并迭代实现,对比了 C 与 Rust 两条路线,关注运行性能、代码复杂度和编译后的动态库体积。

第一轮:C 体积更小,Rust 解析更快

初版扩展的动态库体积如下:

实现方式 动态库体积
C 14 KB
Rust,使用 rusqlite 321 KB
Rust,使用 sqlite-loadable-rs 298 KB

C 扩展的体积明显更小,但初版运行性能落后于两个 Rust 实现。实验将这一差异归因于数字解析环节:Rust 对应的浮点解析实现,比初版 C 使用的 strtod 更快。

这里值得区分两个指标:动态库体积小,并不意味着数字解析速度一定更快。

第二轮:替换 C 的数字解析实现

接下来的优化没有更换语言,而是为 C 编写十进制数字解析函数,并采用 Clinger 快速路径(Clinger’s fast path)。

在 200 万行数据的测试中,各实现的每行净耗时如下,数值越低越好:

数据类型 初版 C 优化后 C Rust:rusqlite Rust:sqlite-loadable-rs
混合数据 67 ns 19 ns 46 ns 41 ns
仅整数 25 ns 16 ns 36 ns 32 ns
仅小数 106 ns 18 ns 55 ns 47 ns

优化后的 C 实现在三组测试中都取得了最低的每行净耗时。其中,小数数据的变化最明显:从 106 ns 降至 18 ns。

这次变化说明,在该原型中,数字解析实现的选择足以改变性能对比结果,不能只根据实现语言判断运行速度。

如何理解这组结果

这类实验适合拆开看:

  • 体积方面:初版 C 动态库为 14 KB,小于两个 Rust 版本。
  • 初版性能方面:两个 Rust 实现均快于使用 strtod 的初版 C。
  • 优化后性能方面:采用 Clinger 快速路径的 C 实现在三组测试中均领先。

对于写好标智库读者关心的技术选型问题,这个案例更适合作为“识别并优化具体解析环节”的参考,而不是 C 与 Rust 的通用性能排名。

这些结果只适用于本次原型比较。 当前材料没有给出完整的测试环境、输入分布、编译选项及误差范围,也没有展开代码复杂度的具体对比。因此,不能据此认定某种语言普遍更快,也不能将初版的体积数据直接视为所有构建配置下的结果。

实际采用类似扩展前,应先明确清理与解析规则,再结合目标数据和部署条件验证性能、体积与行为是否符合需求。

Top comments (0)