Rozważmy fragmentCzy Rust może zoptymalizować kopie bitowe podczas ruchu obiektu w przyszłości?
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);
}
Typowym result programu jest
0x7fffc1239890
0x7fffc1229890
gdzie adresy są różne.
Wygląda na to, że duża tablica dummy
została skopiowana zgodnie z oczekiwaniami w implementacji przenoszenia kompilatora. Niestety, może to mieć nietrywialny wpływ na wydajność, ponieważ dummy
jest bardzo dużą tablicą. Ten wpływ może zmusić ludzi do wyboru argumentu przekazującego przez odniesienie, nawet jeśli funkcja faktycznie "konsumuje" argument koncepcyjnie.
Od Foo
nie pochodzi Copy
, obiekt o
jest przesuwany. Ponieważ Rust zabrania dostępu do przeniesionego obiektu, co uniemożliwia bar
"ponowne użycie" oryginalnego obiektu o
, zmuszając kompilator do wygenerowania potencjalnie drogiej kopii bitowej? Czy istnieje zasadnicza trudność, czy też zobaczymy, że kompilator kiedyś zoptymalizuje tę bitową kopię?
Rustc optymalizuje ruchy. Nie robi tego w tym przypadku, prawdopodobnie dlatego, że llvm nie wstawił paska. Może to być spowodowane tym, że próbujesz obserwować wartości wskaźnika, a llvm nie jest pewien, czy można go bezpiecznie zoptymalizować. Próbowałem go bez użycia printów ': p' i użyłem test :: black_box, a kopia znika ze złożenia. – Manishearth
@ '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ' LLVM jest po prostu złe w usuwaniu ruchów dużych tablic. – Veedrac