Rust可以在某天移动对象期间优化掉逐位复制吗?

时间:2016-07-25 15:03:59

标签: rust move-semantics

考虑代码段

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);
}

该程序的典型result

0x7fffc1239890
0x7fffc1229890

地址不同。

显然,大型数组dummy已被复制,正如编译器的移动实现中所期望的那样。不幸的是,这可能会产生非平凡的性能影响,因为dummy是一个非常大的数组。这种影响可以迫使人们选择通过引用来传递参数,即使函数在概念上实际上“消耗”了参数。

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

1 个答案:

答案 0 :(得分:21)

鉴于在Rust中(与C或C ++不同),值的地址不重要, language 没有任何内容可以阻止副本的省略。

然而,今天rustc没有优化任何东西:所有优化都委托给LLVM,而且你似乎已经在这里遇到了LLVM优化器的限制(目前还不清楚这种限制是否是由于LLVM接近C& #39;语义或只是一个遗漏)。

因此,有两种方法可以改善代码生成:

  • 教授LLVM以执行此优化(如果可能)
  • 教学rustc来执行此优化(优化通过即将生效,因为它具有MIR)

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