有朝一日,Rust 可以在对象移动期间优化掉按位复制吗?
Can Rust optimise away the bit-wise copy during move of an object someday?
考虑片段
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
是一个非常大的数组。这种影响会迫使人们选择通过引用传递参数,即使函数实际上 "consumes" 概念上的参数。
由于 Foo
不派生 Copy
,对象 o
被移动。由于 Rust 禁止访问移动的对象,是什么阻止了 bar
到 "reuse" 原始对象 o
,迫使编译器生成一个潜在的昂贵的按位副本?是否存在基本困难,或者我们有一天会看到编译器优化掉这个按位复制?
鉴于在 Rust 中(与 C 或 C++ 不同)值的地址不被认为是重要的,语言 没有任何东西可以防止复制的省略.
然而,今天 rustc 没有优化任何东西:所有的优化都委托给了 LLVM,你似乎在这里遇到了 LLVM 优化器的限制(目前还不清楚这个限制是由于 LLVM 接近 C 的语义还是只是一个遗漏)。
因此,有两种改进代码生成的途径:
- 教 LLVM 执行此优化(如果可能)
- 教 rustc 执行此优化(优化过程即将进入 rustc,因为它有 MIR)
但现在您可能只是想避免在堆栈上分配如此大的对象,您可以 Box
例如。
考虑片段
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
是一个非常大的数组。这种影响会迫使人们选择通过引用传递参数,即使函数实际上 "consumes" 概念上的参数。
由于 Foo
不派生 Copy
,对象 o
被移动。由于 Rust 禁止访问移动的对象,是什么阻止了 bar
到 "reuse" 原始对象 o
,迫使编译器生成一个潜在的昂贵的按位副本?是否存在基本困难,或者我们有一天会看到编译器优化掉这个按位复制?
鉴于在 Rust 中(与 C 或 C++ 不同)值的地址不被认为是重要的,语言 没有任何东西可以防止复制的省略.
然而,今天 rustc 没有优化任何东西:所有的优化都委托给了 LLVM,你似乎在这里遇到了 LLVM 优化器的限制(目前还不清楚这个限制是由于 LLVM 接近 C 的语义还是只是一个遗漏)。
因此,有两种改进代码生成的途径:
- 教 LLVM 执行此优化(如果可能)
- 教 rustc 执行此优化(优化过程即将进入 rustc,因为它有 MIR)
但现在您可能只是想避免在堆栈上分配如此大的对象,您可以 Box
例如。