27

考虑片段

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

地址不同的地方。

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

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

4

1 回答 1

26

鉴于在 Rust(与 C 或 C++ 不同)中,值的地址并不重要,就语言而言,没有什么可以防止复制的省略。

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

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

  • 教 LLVM 执行此优化(如果可能)
  • 教 rustc 执行这个优化(因为 rustc 有 MIR,优化通道即将到来)

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

于 2016-07-25T15:19:00.153 回答