Need some help for a book intro to JMH

Bruce Eckel bruceteckel at gmail.com
Fri Aug 12 17:33:22 UTC 2016


I'm using JMH in parts of an upcoming Java book. I've got some other parts
working but have gotten stuck on the introduction because JMH is producing
rather unexpected results.

I'm using Arrays.setAll() vs Arrays.parallelSetAll() here because I've
already shown the perils of trying to write your own benchmarking system
using that example and it has demonstrated it well (I can include the whole
section if you want but I wanted to start by focusing on the JMH part).

To reproduce it:
git clone https://github.com/BruceEckel/OnJava8-Examples
cd OnJava8-Examples
gradlew :verifying:jmh

So my questions are:
1. Is Arrays.setAll() vs Arrays.parallelSetAll() just too tricky and subtle
as an example, or are there JMH annotations I can add to fix this?
2. Is there a better introductory example I should be using? (Ideally such
an example would also show problems when using simple timing).

Here is the introductory section (so far), including test results:

### Introducing JMH

At this writing, the only microbenchmark system for Java that produced
decent
results is The *Java Microbenchmarking Harness*
[JMH](http://openjdk.java.net/projects/code-tools/jmh/). Configuring and
using
JMH by hand is tricky, but fortunately the book's `build.gradle` automates
everything so you don't need to struggle with it.

It's possible to write JMH code so it can be run from the command line, but
the
recommended approach is to let the JMH system run the tests for you. JMH
attempts to make the writing of benchmarks as easy as possible. For
example, we
can rewrite `BadMicroBenchmark.java` to use JMH:

```java
// verifying/jmhtests/ParallelSetAll.java
package verifying.jmhtests;
import java.util.*;
import org.openjdk.jmh.annotations.*;

@State(Scope.Thread)
public class ParallelSetAll {
  private long[] la;
  @Setup
  public void setup() {
    la = new long[20_000_000];
  }
  @Benchmark
  public void setAll() {
    Arrays.setAll(la, n -> n);
  }
  @Benchmark
  public void parallelSetAll() {
    Arrays.parallelSetAll(la, n -> n);
  }
}
```

To run the benchmark, you use an explicit command (executed from the root
directory of the example code), so the benchmarking doesn't happen as part
of
the normal `gradlew run` command:

```
gradlew :verifying:jmh
```

You'll see that it takes a *long* time, around 15 minutes depending on your
machine. Each test has a default of 20 warmup iterations, and 20 test
iterations. The output indicates where the results are summarized in a
`results.txt` file. This is from my 2-core laptop running Windows 10:

```
Benchmark                       Mode  Cnt   Score   Error  Units
ParallelSetAll.parallelSetAll  thrpt  200  33.496 ± 0.125  ops/s
ParallelSetAll.setAll          thrpt  200  32.936 ± 1.254  ops/s
```

On my 4-core laptop running Windows 10, the results are different:

```
Benchmark                       Mode  Cnt   Score   Error  Units
ParallelSetAll.parallelSetAll  thrpt  200  19.621 ± 0.254  ops/s
ParallelSetAll.setAll          thrpt  200  30.875 ± 0.038  ops/s
```

Here are the results from the same laptop, running Linux Mint:

```
Benchmark                       Mode  Cnt   Score   Error  Units
ParallelSetAll.parallelSetAll  thrpt  200  31.335 ± 0.023  ops/s
ParallelSetAll.setAll          thrpt  200  34.842 ± 0.066  ops/s
```

On the Appveyor *Continuous Integration* (CI) server, which provides two
dedicated cores, the results are:

```
Benchmark                       Mode  Cnt   Score   Error  Units
ParallelSetAll.parallelSetAll  thrpt  200  98.987 ± 0.644  ops/s
ParallelSetAll.setAll          thrpt  200  53.148 ± 0.165  ops/s
```

On Travis-ci, which provides two "bursted" cores, the results are:

```
Benchmark                       Mode  Cnt   Score   Error  Units
ParallelSetAll.parallelSetAll  thrpt  200  63.895 ± 6.768  ops/s
ParallelSetAll.setAll          thrpt  200  54.631 ± 0.298  ops/s
```



-- Bruce Eckel
www.MindviewInc.com <http://www.mindviewinc.com/>
Blog: BruceEckel.github.io
www.WinterTechForum.com
www.AtomicScala.com
www.Reinventing-Business.com
http://www.TrustOrganizations.com <http://www.ScalaSummit.com>


More information about the jmh-dev mailing list