Consider the snippet
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);
}
A typical result of the program is
0x7fffc1239890
0x7fffc1229890
where the addresses are different.
Apparently, the large array dummy
has been copied, as expected in the compiler's move implementation. Unfortunately, this can have non-trivial performance impact, as dummy
is a very large array. This impact can force people to choose passing argument by reference instead, even when the function actually "consumes" the argument conceptually.
Since Foo
does not derive Copy
, object o
is moved. Since Rust forbids the access of moved object, what is preventing bar
to "reuse" the original object o
, forcing the compiler to generate a potentially expensive bit-wise copy? Is there a fundamental difficulty, or will we see the compiler someday optimise away this bit-wise copy?
:p
prints and used test::black_box instead, and the copy vanishes from the assembly. – Nickeliferousbar
is getting inlined. LLVM is just bad at removing moves of large arrays. – DibaNRVO
tag are related to this: github.com/rust-lang/rust/labels/A-mir-opt-nrvo – Chabliso
dropping guaranteed in this case? In view of it was moved out tobar()
, what's the point where theo
memory would free up? – Schoolman