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