Rust可以在某一天移动对象时优化掉逐位复制吗



考虑片段

struct Foo {
    dummy: [u8; 65536],
}
fn bar(foo: Foo) {
    println!("{:p}", &foo)
}
fn main() {
    let o = Foo { dummy: [42u8; 65536] };
    println!("{:p}", &o);
    bar(o);
}

程序的典型结果是

0x7fffc1239890
0x7fffc1229890

其中地址不同。

显然,正如编译器的move实现中所预期的那样,大数组dummy已经被复制。不幸的是,由于dummy是一个非常大的数组,这可能会对性能产生不小的影响。这种影响可能会迫使人们选择通过引用传递参数,即使函数实际上在概念上"消耗"了参数。

由于Foo不导出Copy,因此对象o被移动。既然Rust禁止访问移动的对象,是什么阻止了bar"重用"原始对象o,迫使编译器生成一个潜在的昂贵的逐位副本?是否存在根本性的困难,或者我们会看到编译器有一天会优化掉这个逐位副本吗?

在Rust中(与C或C++不同),值的地址并不重要,因此在语言中没有任何东西可以阻止副本的省略。

然而,如今rustc并没有优化任何东西:所有的优化都委托给LLVM,而且您似乎在这里遇到了LLVM优化器的限制(不清楚这个限制是由于LLVM接近C的语义还是只是一个遗漏)。

因此,有两种改进代码生成的途径:

  • 教导LLVM执行此优化(如果可能)
  • 教导rustc执行此优化(既然rustc有了MIR,优化过程就要到了)

但现在您可能只是想避免在堆栈上分配这么大的对象,例如可以Box

相关内容

  • 没有找到相关文章

最新更新