“零开销抽象”常被当口号。这篇给它做实验:把 7 组高层写法与手写底层写法编译成汇编逐行比较,再看真正有开销的抽象是哪些,以及优化关闭时这个说法还成不成立。
Newtype 包装 高层 2 条指令 / 手写 2 条指令 逐行相同: 是 Option<&T> vs 裸指针判空 高层 3 条指令 / 手写 3 条指令 逐行相同: 是 iter().sum() vs for 循环 高层 60 条指令 / 手写 65 条指令 逐行相同: 否 map().sum() vs 手写累加 高层 65 条指令 / 手写 65 条指令 逐行相同: 否 泛型 max<T> vs 具体类型 高层 3 条指令 / 手写 3 条指令 逐行相同: 是 闭包调用 vs 直接计算 高层 3 条指令 / 手写 3 条指令 逐行相同: 是 &dyn Fn 调用 vs fn 指针调用 高层 3 条指令 / 手写 3 条指令 逐行相同: 否
迭代器链的汇编见Iterator 链的性能;泛型单态化见泛型单态化。
下标访问 v[i](有边界检查) 带安全检查/抽象的 11 条 / 无检查的 2 条 checked_add vs 回绕加 带安全检查/抽象的 4 条 / 无检查的 2 条 Rc 克隆 vs 复制 u32 带安全检查/抽象的 7 条 / 无检查的 2 条
编译:成功 debug : Newtype + 迭代器 fold: 27.36 ms 裸 f64 + for 循环: 19.63 ms 结果相同: true release: Newtype + 迭代器 fold: 5.06 ms 裸 f64 + for 循环: 4.85 ms 结果相同: true
汇编指令数来自 aarch64 的 -O 输出,换平台数字会不同;耗时为本机单次微基准。