Rust 我是否必须关心'Rc'的开销?

Rust 我是否必须关心'Rc'的开销?,rust,Rust,我是否正确地假设唯一“减慢”Rcs的事情是它检查对象掉落时是否释放?除此之外,取消引用Rc的开销是多少,即我应该关注它吗? 这两种功能几乎一样快吗?或者在速度上有显著差异吗 fn test_with_box() { let b = Box::new(1.0); let x = b * 2; } fn test_with_rc() { let rc = Rc::new(1.0); let x = rc * 2; } 由于test\u with_rc()中的引用对

我是否正确地假设唯一“减慢”
Rc
s的事情是它检查对象掉落时是否释放?除此之外,取消引用
Rc
的开销是多少,即我应该关注它吗?
这两种功能几乎一样快吗?或者在速度上有显著差异吗

fn test_with_box() {
    let b = Box::new(1.0);
    let x = b * 2;
}

fn test_with_rc() {
    let rc = Rc::new(1.0);
    let x = rc * 2;
}
由于
test\u with_rc()
中的引用对象始终只有一个引用,并且在该函数中的行为类似于
(当然是从外部查看,而不是从内部查看)

我怀疑
Rc
s实际上比我想象的要快


注:当谈到“快速”时,我指的是取消引用和分配/取消分配。

要回答您的问题,您可以转到
测试
板条箱,其中包含一个基准测试解决方案(这需要每晚一次):

现在编译并运行以下命令:

$ rustc --test -O rc.rs && ./rc --bench

running 2 tests
test bench_box ... bench:          22 ns/iter (+/- 0)
test bench_rc  ... bench:          22 ns/iter (+/- 0)

test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured
发生了什么事?RC显然已经完全编制完毕。应该如此,因为我们还没有克隆它。因此,将相应的
fn
更改为:

fn test_with_rc() {
    let rc = Rc::new(1.0);
    test::black_box(*rc.clone() * 2.0);
}
我们得到以下结果:

running 2 tests
test bench_box ... bench:          23 ns/iter (+/- 1)
test bench_rc  ... bench:          25 ns/iter (+/- 1)

test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured
所以,可以说,在考虑RC引起的开销之前,您可能需要考虑其他问题。

RC
非常非常便宜。它不像
T
便宜很多(装箱值在微观优化方面相对昂贵),但其效率几乎不低于
Box

它就像是
,但是有一对额外的单词用于强引用计数和弱引用计数,并且只需要触摸创建
Rc
(初始化值),克隆
Rc
(增加引用计数),删除
Rc
(减少refcount并运行析构函数(如果合适),以及从
弱降级到/升级到
(增加两个refcount中的一个,减少另一个)


取消引用是一种简单的内存操作,就像使用
Box

一样,对于性能问题,唯一可以知道的方法是在现场对其进行分析。微基准测试并不合适。但知道开销是否在几个周期、几微秒、几毫秒等范围内仍然很有趣:-)。Rc显然更多的是在“几个周期”的范围内。Rc显然是完全编译出来的,我不认为你可以说它是优化出来的。如果您查看,您可以看到
test\u with_box
调用
@je\u mallocx(i64 8,i32 0)
test\u with_rc
调用
@je\u mallocx(i64 24,i32 0)
,因此这两个块不会是同一个程序集。另外还有4条关于
Rc
的说明。我想补充一点,降级/升级是稳定的
running 2 tests
test bench_box ... bench:          23 ns/iter (+/- 1)
test bench_rc  ... bench:          25 ns/iter (+/- 1)

test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured