Skip to content

引用大量使用会不会有性能损耗

约 502 字大约 2 分钟

底层原理

2025-06-03

简单结论

  • 引用是一次跳转(一级指针)

  • 不会产生额外跳转

  • 在 Release 模式下,性能几乎与直接访问相同

  • Rust 的编译器(LLVM)会极度优化引用使用


举个例子

fn by_ref(x: &i32) -> i32 {
    *x + 1
}
fn by_val(x: i32) -> i32 {
    x + 1
}

在编译后的 Release 模式中,这两个函数在汇编级别几乎一样,不会因为 &i32 多一个跳转。


🔧 底层原理解释

引用本质上是

&T —— 栈上的一个指针(8字节,在64位系统中)

访问引用的值就是一次 间接寻址(一级跳转)

mov rax, [rbp - 8]   ; 加载指针
mov rcx, [rax]       ; 通过指针取值,一级跳转

如果是 &Box<T>&Rc<T> 那就是:

引用 -> Box -> T     // 这时候确实有两次跳转

LLVM 优化能力非常强

Rust 编译器基于 LLVM,可以进行:

  • 引用去除优化(alias analysis)

  • 内联解引用

  • 逃逸分析(escape analysis)

  • 零开销抽象(zero-cost abstraction)

这意味着如果引用没有跨函数、没有并发或生命周期冲突,LLVM 可以自动展开成值访问


⚠️ 哪些情况下引用可能有轻微性能损耗?

情况说明
过度嵌套引用(如 &&&&TLLVM 可能不完全优化
动态分发(如 &dyn Trait涉及 vtable 跳转,有额外开销
拿引用但频繁跨线程传递线程同步(如 Arc<Mutex<_>>)有系统级成本
使用引用导致阻止编译器优化比如影响内联、vectorization

✅ 总结

问题答案
&T 是不是指针?是,一次跳转
会不会导致二次跳转?通常不会,除非引用了智能指针等
大量使用引用会不会变慢?不会,除非你写了很复杂的嵌套、动态调度等
Rust 编译器会优化引用开销吗?会,尤其是 Release 模式下非常高效