如果我在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纳秒。
但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倍。
我是否编写了糟糕的基准测试,或者这是一个性能问题?
回复评论中提出的问题:
>
我使用总是在发布模式下运行的cargo bench
运行Rust的基准测试。
Java基准测试框架(JavaBenchmarkFramework,JMH)为每个调用创建一个新对象,即使它是静态
类和最终
变量。如果我在测试方法中添加一个随机创建,我得到43 ns/op。
我将提供另一半的解释,因为我不知道<代码>数学。日志用@hospotintrisccandidate
注释,这意味着对于这样的操作,它将被本机CPU指令替换:thinkInteger。位计数
可以进行大量移位,也可以使用速度更快的直接CPU指令。
有这样一个非常简单的程序:
public static void main(String[] args) {
System.out.println(mathLn(20_000));
}
private static long mathLn(int x) {
long result = 0L;
for (int i = 0; i < x; ++i) {
result = result + ln(i);
}
return result;
}
private static final long ln(int x) {
return (long) Math.log(x);
}
并运行它:
java -XX:+UnlockDiagnosticVMOptions
-XX:+PrintInlining
-XX:+PrintIntrinsics
-XX:CICompilerCount=2
-XX:+PrintCompilation
package/Classname
它将生成许多行,但其中之一是:
@ 2 java.lang.Math::log (5 bytes) intrinsic
使这个代码非常快。
我真的不知道这是什么时候发生的,是怎么发生的。。。
答案由@kennytm给出:
export RUSTFLAGS='-Ctarget-cpu=native'
修复问题。之后,结果是:
test tests::bench_ln ... bench: 43 ns/iter (+/- 3)
test tests::bench_rnd ... bench: 5 ns/iter (+/- 0)
我认为38(±3)足够接近31.555(±0.234)。
问题内容: 为什么比Java 慢?换句话说,为什么优于? 当我查看中的实现时,速度似乎应该是相同的: ArrayList.size() ArrayList.isEmpty() 如果我们只编写一个简单的程序来获取两种方法所花费的时间,那么在所有情况下这种情况都将花费更多,为什么会这样呢? 这是我的TestCode; 在所有情况下都在这里。为什么? 问题答案: 您的测试代码有缺陷。 只需颠倒顺序,即先
我在Surface Pro 2平板电脑上运行Windows8.1x64和Java7更新45x64(没有安装32位Java)。 下面的代码在i类型为long时占用1688ms,在i类型为int时占用109ms。为什么在64位JVM的64位平台上,long(64位类型)比int慢一个数量级? 我唯一的猜测是,CPU加一个64位整数比加一个32位整数需要更长的时间,但这似乎不太可能。我怀疑Haswell
我正在学习Java,刚刚发现了这个关于该语言的微妙事实:如果我声明两个具有相同元素的整数数组,并使用比较它们,结果是。为什么会出现这种情况?比较值不应该为吗? 提前感谢!
问题内容: 从2010年的计算机语言基准游戏中可以看出: Go平均比C慢10倍 Go比Java慢3倍! 考虑到Go编译器会生成要执行的本机代码,这怎么可能? Go的编译器不成熟?还是Go语言存在一些内在问题? 编辑: 大多数答案否认Go语言的内在缓慢,声称问题出在不成熟的编译器中。 因此,我进行了一些自己的测试来计算斐波那契数:迭代算法在Go(freebsd,6g)中以与C(带有O3选项)一样的速
问题内容: 在调查使用以及将整数原语转换为字符串的简短辩论时,我编写了以下JMH微基准测试: 我在Linux机器上的两个Java VM上都使用默认的JMH选项运行了它(最新的Mageia 4 64位,Intel i7-3770 CPU,32GB RAM)。第一个JVM是Oracle JDK 8u5 64位提供的: 有了这个JVM,我得到了我所期望的: 也就是说,由于创建对象和附加空字符串会产生额外
问题内容: 输出: 为什么这样的输出?我期望作为第一种情况的结果。 问题答案: 区别在于6.5可以完全以float和double表示,而3.2不能完全以两种类型表示。并且两个最接近的近似是不同的。 float和double之间的相等比较首先将float转换为double,然后将两者进行比较。因此数据丢失。 您不应该比较浮点数或双精度数是否相等。因为您不能真正保证分配给float或double的数字