optimization - ¿Puedo devolver eficientemente un objeto por valor en Rust?
return-value-optimization (1)
Me gustaría inicializar un objeto grande con una función. Actualmente tengo:
fn initialize(mydata: &mut Vec<Vec<MyStruct>>) { /* ... */ }
Prefiero tener:
fn initialize() -> Vec<Vec<MyStruct>> { /* ... */ }
Escuché que C ++ a menudo implementa la optimización del valor de retorno (RVO), si tienes suerte y tienes un buen compilador. ¿Podemos desactivar la copia aquí y que sea devuelta por un puntero oculto que se pasa a la función? ¿RVO es parte del lenguaje o una optimización opcional?
Sí, por supuesto, deberías escribir
fn initialize() -> Vec<Vec<MyStruct>> { ... }
(Por cierto, un
Vec
no es tan grande, solo tiene 3 enteros del tamaño de un puntero)
Rust tiene RVO, y esto se anuncia en guías . Puede verlo usted mismo con este código:
#[inline(never)]
fn initialize() -> Vec<i32> {
Vec::new()
}
fn main() {
let v = initialize();
}
Si compila este programa en modo de lanzamiento en el patio de juegos , generando ensamblaje, entre todo lo demás verá esto:
playground::initialize:
movq $4, (%rdi)
xorps %xmm0, %xmm0
movups %xmm0, 8(%rdi)
retq
Vec::new()
estaba en línea, pero puede ver la idea: la dirección de la nueva instancia de
Vec
se pasa a la función en
%rdi
, y la función almacena los campos
Vec
directamente en esta memoria, evitando copias innecesarias a través de la pila.
Así es como se llama:
playground::main:
subq $24, %rsp
movq %rsp, %rdi
callq playground::initialize
Puede ver que eventualmente la instancia de
Vec
se colocará directamente en la memoria de la pila.