在将 Rust 从版本 1.36.0 升级到 1.38.0 后,我注意到我的程序运行速度变慢了——大约慢了 50%。
使用 perf
,我发现新版本中程序一半的时间花费在 alloc::vec::Vec<T>::retain
上。在旧版本中,这个函数甚至都没有出现过。为什么 retain
在 1.38.0 版本中会花费这么长时间呢?
对 retain
的调用如下所示:
some_vec.retain(|&x| x < DEADLINE);
deadline
是一个常量 u32
,而 some_vec
则是一个 Vec<u32>
。
我在两个版本中都没有使用 retain
函数来运行程序。这种情况下,在平均值上 1.38.0 的速度仍然比 1.36.0 慢,但只有约 10% 左右,而不是之前看到的超过 50%。
回顾一下测试中发生的事情:
版本 1.36.0
- 使用
retain
:约 18 秒 - 未使用
retain
:约 11 秒
版本 1.38.0
- 使用
retain
:约 28 秒 - 未使用
retain
:约 12 秒
要获取可重现的示例,您可以尝试:
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);
}
使用 cargo +1.36.0 run --release
命令,然后再执行 cargo +1.38.0 run --release
命令。
对于这个小例子,我得到了以下结果:
$ cargo +1.36.0 run --release
Program took: 4.624297719s
$ cargo +1.38.0 run --release
Program took: 8.293383522s