bigywater.tech
Rust · 40

泛型单态化

泛型在 Rust 里是零运行时开销的,代价记在编译期:每个具体类型一份代码。这篇不空谈「代码膨胀」,而是真的数符号、量 .o 文件大小、量编译时间,并和 &dyn 版本对比 —— 结果比「泛型一定更大」要微妙。

8 个
同一个泛型函数在 8 种类型上生成的函数个数
2,568 → 9,792 B
泛型版 .o 大小从 1 种到 8 种类型
45 → 84 ms
编译时间从 1 种到 8 种类型(小例子)

每个类型一份

实测 · 本机执行输出
  describe 在 8 种类型上使用,汇编里生成的 describe 函数符号:8 个
    __RINvCs4bCzEYfDy3k_4u40a8describeReEB2_
    __RINvCs4bCzEYfDy3k_4u40a8describecEB2_
    __RINvCs4bCzEYfDy3k_4u40a8describedEB2_
    __RINvCs4bCzEYfDy3k_4u40a8describefEB2_
    __RINvCs4bCzEYfDy3k_4u40a8describehEB2_
    __RINvCs4bCzEYfDy3k_4u40a8describelEB2_
    __RINvCs4bCzEYfDy3k_4u40a8describesEB2_
    __RINvCs4bCzEYfDy3k_4u40a8describexEB2_

代码体积

实测 · 本机执行输出
     不同类型数        泛型版 .o 字节     &dyn 版 .o 字节
         1            2,568            6,248
         2            4,528            6,712
         4            6,608            7,736
         8            9,792            9,120

.o 文件大小是粗略指标(包含符号表、元数据等),不等于最终可执行文件里的代码段大小。

编译时间

实测 · 本机执行输出
  泛型版 1 种类型:45 ms;泛型版 8 种类型:84 ms;&dyn 版 8 种类型:66 ms

更多关于编译时间与二进制体积的分析见编译时间分析与二进制体积分析;分发方式的运行时对比见静态分发与动态分发性能对比。

分步演示

单态化
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / rustc 1.98.1(brew)/ cargo 1.98.1;单个文件用 rustc 直接编译,需要依赖时用 cargo(经代理从 crates.io 下载);计时用 std::time::Instant,数字每次运行会有小幅抖动。.o 体积来自 --emit=obj -O -C codegen-units=1;时间为 3 次中位数,rustc 单次编译 40–90 ms 量级,噪声不小
    • 没有验证:大型泛型函数上的体积膨胀倍数、-C opt-level=s/z 的影响、-Zshare-generics、LTO 对重复实例的合并、泛型代码对指令缓存的影响
    京ICP备2026067502号-1京公网安备11010502063487号