【发布时间】:2017-12-15 16:38:18
【问题描述】:
如果我在 Rust 中运行这些基准测试:
#[bench]
fn bench_rnd(b: &mut Bencher) {
let mut rng = rand::weak_rng();
b.iter(|| rng.gen_range::<f64>(2.0, 100.0));
}
#[bench]
fn bench_ln(b: &mut Bencher) {
let mut rng = rand::weak_rng();
b.iter(|| rng.gen_range::<f64>(2.0, 100.0).ln());
}
结果是:
test tests::bench_ln ... bench: 121 ns/iter (+/- 2)
test tests::bench_rnd ... bench: 6 ns/iter (+/- 0)
121-6 = 115 ns 每次 ln 调用。
但 Java 中的基准相同:
@State(Scope.Benchmark)
public static class Rnd {
final double x = ThreadLocalRandom.current().nextDouble(2, 100);
}
@Benchmark
public double testLog(Rnd rnd) {
return Math.log(rnd.x);
}
给我:
Benchmark Mode Cnt Score Error Units
Main.testLog avgt 20 31,555 ± 0,234 ns/op
Rust 中的日志比 Java 慢约 3.7 倍 (115/31)。
当我测试斜边实现 (hypot) 时,Rust 中的实现比 Java 快 15.8 倍。
我是否编写了糟糕的基准测试或者这是一个性能问题?
对 cmets 中提出的问题的回答:
"," 是我国的小数分隔符。
我使用
cargo bench运行 Rust 的基准测试,它始终在发布模式下运行。Java 基准框架 (JMH) 会为每次调用创建一个新对象,即使它是一个
static类和一个final变量。如果我在测试方法中添加随机创建,我得到 43 ns/op。
【问题讨论】:
-
Java 不适合用作基准测试吗?我的意思是 java 很好,但在某些情况下,它太好了
-
您可能比 log 函数更多地对随机数生成器进行基准测试。另外,我相信 Rust 只是使用系统数学库,所以对
log的纯调用应该与它在 C 中的调用相同(不知道 Java)。 -
你能用
RUSTFLAGS='-Ctarget-cpu=native' cargo bench重新运行测试吗? -
@SimonByrne 如果 OP 不小心对 RNG 进行了基准测试,那会不会被 仅 测试 RNG 的
bench_rnd函数所抵消?这就是为什么 OP 减去了两个 Rust 基准测试时间——为ln函数做一个纯粹的基准测试。我同意它应该只是调用系统数学库。 -
我对java一无所知,但你确定x是更新的吗?
标签: java floating-point rust microbenchmark jmh