§Install by building from the source

1
2
3
hg clone http://hg.openjdk.java.net/code-tools/jmh/ jmh
cd jmh
mvn clean install -DskipTests

§Create new project to use JMH

1
2
3
4
5
6
7
$ mvn archetype:generate \
-DinteractiveMode=false \
-DarchetypeGroupId=org.openjdk.jmh \
-DarchetypeArtifactId=jmh-java-benchmark-archetype \
-DgroupId=org.sample \
-DartifactId=my-jmh-test \
-Dversion=1.0

Modify MyBenchmark.java so that it looks something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package org.sample;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import org.openjdk.jmh.infra.Blackhole;

public class MyBenchmark {

@State(Scope.Thread)
public static class MyState {
public int[] arr = new int[2];
public int i = 0;
}

@Benchmark
public int testMethod(MyState s) {
return s.arr[s.i+1];
}

public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(MyBenchmark.class.getSimpleName())
.warmupIterations(1)
.measurementIterations(1)
.forks(1)
.build();

new Runner(opt).run();
}
}

Run it using:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ mvn package && \
java -Xcomp \
-XX:+UnlockDiagnosticVMOptions \
-XX:CompileCommand='print,*.testMethod' \
-cp target/benchmarks.jar:target/my-jmh-test-1.0.jar \
org.sample.MyBenchmark > tmp.asm
$ # or
$ mvn package && \
java -Xcomp \
-XX:+UnlockDiagnosticVMOptions \
-XX:CompileCommand='print,*.testMethod' \
-jar target/benchmarks.jar -wi 5 -i 1 -f 1 > tmp.asm
$ # five warmup, one iteratino, one fork; see `java -jar target/benchmark.jar -h` for complete list of accepted options

The corresponding assembly looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
0x00007f15119a0c18: mov     0x10(%rdx),%eax   ; implicit exception: dispatches to 0x00007f15119a0c54
0x00007f15119a0c1b: shl $0x3,%rax ;*getfield arr
; - org.sample.MyBenchmark::testMethod@1 (line 51)

0x00007f15119a0c1f: mov 0xc(%rdx),%esi ;*getfield i
; - org.sample.MyBenchmark::testMethod@5 (line 51)

0x00007f15119a0c22: incl %esi
0x00007f15119a0c24: movsxd %esi,%rdi
0x00007f15119a0c27: cmp 0xc(%rax),%esi ; implicit exception: dispatches to 0x00007f15119a0c59
0x00007f15119a0c2a: jnb 0x7f15119a0c63
0x00007f15119a0c30: mov 0x10(%rax,%rdi,4),%eax ;*iaload
; - org.sample.MyBenchmark::testMethod@10 (line 51)

The jnb instruction is for array bounds check, because array size info is located at 0xc offset of the base pointer.

§Reference