我用 rust 编写了两个空函数,希望用它们来测试向量上 retain 的使用或在迭代器上 filter 的使用,在为每种情况编写空函数后,在运行程序时,我注意到每个函数的持续时间之间存在巨大差异,这意味着在当前空函数中添加任何逻辑都会导致对其执行时间得出错误的结论。
use std::time::Instant;
fn use_filter() {
}
fn use_retain() {
}
fn run_multiple(f: fn(), times: u64) {
for _ in 0..times {
f()
}
}
fn main() {
let iter_count: u32 = 1_000_000_000;
let _start_1 = Instant::now();
run_multiple(use_filter, iter_count as u64);
let duration = Instant::now() - _start_1;
println!("Use Filter duration: {:?}", duration / iter_count);
let _start_2 = Instant::now();
run_multiple(use_retain, iter_count as u64);
let duration = Instant::now() - _start_2;
println!("Use Retain duration: {:?}", duration / iter_count);
}
预期输出
Use Filter duration: xns
Use Retain duration: xns
其中 x 对于两个函数来说都是相同的,因为它们都是空的并且不执行任何操作
实际产量
Use Filter duration: 8ns
Use Retain duration: 10ns
什么可以解释 rust 编程语言中空函数的执行时间差异很大。
问题中给出的结果完全是由于噪音,没有提供任何有用的信息。代码编译后的结果如下
也就是说,您测量的时间差是发出两次调用 所用的时间
Instant::now()
,中间没有任何间隔。没有区别。您看到的时间差是由 的实现不准确Instant::now()
、线程调度或一般噪音造成的。微基准测试有时可以实现可重复的亚纳秒精度结果,但这需要在多个循环迭代中进行时间测量,减少系统噪声,考虑编译器消除代码、ILP、可变 CPU 时钟、热节流和许多其他混杂因素等。
最好为此使用基准测试工具,对输入进行黑盒测试,然后现场查看生成的程序集¹。
即使如此,微基准测试也可能无法代表真实的性能,因为它将单独测量你的代码,而不考虑真实程序中周围代码的缓存压力和分支预测的影响。
¹从线束中提取代码将会改变生成的程序集