Memory 克隆语句是否进行过优化?
我有如下类似的代码Memory 克隆语句是否进行过优化?,memory,rust,clone,Memory,Rust,Clone,我有如下类似的代码 let x = Arc::new(Mutex::new(Thing::new())); work_on_data(x.clone()); do_more_work_on_data(x.clone()); x在第二个函数之后不使用,因此不需要第二个克隆。我应该手动删除克隆(),还是对其进行了优化?克隆可能会打印某些内容或写入文件。优化克隆输出会改变行为,因此无法完成 当然,如果编译器完全了解克隆正在做什么,并且能够计算出它永远不会有副作用,那么它可能会优化它,但不要屏住呼吸
let x = Arc::new(Mutex::new(Thing::new()));
work_on_data(x.clone());
do_more_work_on_data(x.clone());
x
在第二个函数之后不使用,因此不需要第二个克隆。我应该手动删除克隆()
,还是对其进行了优化?克隆可能会打印某些内容或写入文件。优化克隆输出会改变行为,因此无法完成
当然,如果编译器完全了解克隆正在做什么,并且能够计算出它永远不会有副作用,那么它可能会优化它,但不要屏住呼吸
一般来说,如果知道函数总是返回相同的值,请将该值缓存在变量中,而不是多次调用函数。为什么不呢? 优化编译器的首要原则是“仿佛”规则,该规则规定只要编译器能够证明优化是不可见的,任何东西都可以优化 注意:这是一些允许特定优化的语言的基础 例如:
#[derive(Clone, Debug)]
struct MyDummyType(u64);
extern {
fn print_c(_: *const ());
}
#[inline(never)]
fn print(dummy: MyDummyType) {
unsafe { print_c(&dummy as *const _ as *const _) }
}
fn main() {
let x = MyDummyType(42);
print(x.clone());
print(x.clone());
}
产生以下main
:
; Function Attrs: nounwind uwtable
define internal void @_ZN8rust_out4main17h0c6f2596c7f28a79E() unnamed_addr #1 {
entry-block:
tail call fastcc void @_ZN8rust_out5print17h1f2d1a86beea10d7E(i64 42)
tail call fastcc void @_ZN8rust_out5print17h1f2d1a86beea10d7E(i64 42)
ret void
}
编译器完全看穿了我们的代码(实际上我不得不使用extern函数强制它在main
中发出一些代码)
那么,你的案子呢 老实说,这相当困难 具体地说,由于
Drop
,语义可能会发生变化:
- 使用
,do\u more\u work\u on \u data(x.clone())
保证在执行结束后删除,因此x
的任何副作用都将在当前函数结束时执行Drop
- 使用
,dou-more-work\u-on-u-data(x)
可能会在x
的末尾被删除,或者可能会更早地被删除dou-more-work\u-on-u-data
- 无论是
都无效Drop
- 或者在
的最后执行对数据做更多的工作
,这与之后的操作相同删除
- 还是
Drop
实现Mutex
需要调用FFI,因此从优化器的角度来看,它具有明显的效果
因此,这一切都取决于
dou\u more\u work\u\u\u数据是否内联。如果是的话,确实可以优化额外的克隆。如果没有,我就不会屏住呼吸。事实上,他可以移除最后一个克隆人,对吗做更多的工作…
将只占x的位置,因为不再使用x
,这是有意义的。或者我错了?这是非常悲观的。(澄清我的评论)你假设克隆
实现是不透明的,但事实并非如此,只要它对优化器是透明的,优化器就可以保证克隆
没有明显的副作用。对于这种特殊情况,我更关心的是删除,但总体答案显然是肯定的,当然有时它会被优化。我从问题中假设OP熟悉“好像”规则,该规则适用于所有地方,并不专门适用于克隆,但感谢您指出这一点。@MatthieuM。我现在已在本节中补充了这一点。如果你能更好地表达,请随意修改我的答案。