Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is logarithm slower in Rust than in Java?

Tags:

If I run these benchmarks in 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());
}

The result is:

test tests::bench_ln             ... bench:        121 ns/iter (+/- 2)
test tests::bench_rnd            ... bench:          6 ns/iter (+/- 0)

121-6 = 115 ns per ln call.

But the same benchmark in 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);
}

Gives me:

Benchmark    Mode Cnt  Score  Error Units
Main.testLog avgt  20 31,555 ± 0,234 ns/op

The log is ~3.7 times slower (115/31) in Rust than in Java.

When I test the hypotenuse implementation (hypot), the implementation in Rust is 15.8 times faster than in Java.

Have I written bad benchmarks or it is a performance issue?

Responses to questions asked in comments:

  1. "," is a decimal separator in my country.

  2. I run Rust's benchmark using cargo bench which always runs in release mode.

  3. The Java benchmark framework (JMH) creates a new object for every call, even though it's a static class and a final variable. If I add a random creation in the tested method, I get 43 ns/op.

like image 368
Александр Меньшиков Avatar asked Jul 11 '17 14:07

Александр Меньшиков


1 Answers

The answer was given by @kennytm:

export RUSTFLAGS='-Ctarget-cpu=native'

Fixes the problem. After that, the results are:

test tests::bench_ln              ... bench:          43 ns/iter (+/- 3)
test tests::bench_rnd             ... bench:           5 ns/iter (+/- 0)

I think 38 (± 3) is close enough to 31.555 (± 0.234).

like image 74
Александр Меньшиков Avatar answered Oct 06 '22 07:10

Александр Меньшиков