Após atualizar o Rust para a versão 1.38.0 de 1.36.0, notei que meu programa fica mais lento - em cerca de 50%.
Usando perf
, descobri que metade do tempo do programa é gasto na alloc::vec::Vec<T>::retain
nova versão. Na versão mais antiga, essa função nem aparece. Por que retain
demoraria tanto mais tempo na versão 1.38.0?
A chamada para retain
é feita assim:
some_vec.retain(|&x| x < DEADLINE);
deadline
é uma constante u32
e some_vec
é a Vec<u32>
.
Eu executei o programa sem as retain
chamadas nas duas versões. Nesse caso, o 1.38.0 ainda era mais lento, em média, mas apenas em ~ 10% em vez dos> 50% vistos anteriormente.
Para recapitular o que aconteceu nos testes:
Versão 1.36.0
- com
retain
: ~ 18seg - sem
retain
: ~ 11seg
Versão 1.38.0
- com
retain
: ~ 28seg - sem
retain
: ~ 12seg
Para um exemplo reproduzível, você pode tentar:
use std::time::Instant;
fn main() {
let start = Instant::now();
let mut my_vec: Vec<u32>;
for _ in 0..100_000 {
my_vec = (0..10_000).collect();
my_vec.retain(|&x| x < 9000);
my_vec.retain(|&x| x < 8000);
my_vec.retain(|&x| x < 7000);
my_vec.retain(|&x| x < 6000);
my_vec.retain(|&x| x < 5000);
my_vec.retain(|&x| (x < 5) & (x > 2));
}
let duration = start.elapsed();
println!("Program took: {:?}", duration);
}
Com cargo +1.36.0 run --release
e então cargo +1.38.0 run --release
.
Para este pequeno exemplo, obtive:
$ cargo +1.36.0 run --release
Program took: 4.624297719s
$ cargo +1.38.0 run --release
Program took: 8.293383522s
fonte
Respostas:
Em geral, rust.godbolt.org é útil para verificar a qualidade do código gerado (mas não se esqueça de adicionar sinalizadores de otimização!)
No seu caso, o código gerado para
retain
mudou claramente para pior: https://rust.godbolt.org/z/ZhVCDgPortanto, você deve informar isso ao Rust como uma regressão de desempenho.
fonte