Skip to content

Commit e1e43ee

Browse files
committed
Move JHM Binary Tree to native-image/benchmark category
1 parent b84ba48 commit e1e43ee

File tree

10 files changed

+1328
-0
lines changed

10 files changed

+1328
-0
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Compiled class file
2+
target
3+
*.class
4+
default.iprof
5+
6+
# Log file
7+
*.log
8+
9+
# BlueJ files
10+
*.ctxt
11+
12+
# Mobile Tools for Java (J2ME)
13+
.mtj.tmp/
14+
15+
# Package Files #
16+
*.jar
17+
*.war
18+
*.nar
19+
*.ear
20+
*.zip
21+
*.tar.gz
22+
*.rar
23+
24+
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
25+
hs_err_pid*
26+
replay_pid*
27+
28+
### VS Code ###
29+
.vscode/
30+
31+
### Intellij
32+
.idea
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip
18+
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Binary Tree Benchmark
2+
3+
This demo shows how to run a Java Microbenchmark Harness (JMH) benchmark as a native executable.
4+
5+
To build a native executable version of this benchmark you need to run the [Tracing Agent](https://www.graalvm.org/latest/reference-manual/native-image/metadata/AutomaticMetadataCollection/) to supply the reflection configuration to the `native-image` builder.
6+
This has already been done for you to save time and the generated configuration can be found in _src/main/resources/META-INF/native-image/_.
7+
8+
> **Note:** To generate the configuration yourself, ensure that the JMH `fork` parameter is set to `0`, which can be performed from the command line using the option `-f 0`. It can also be achieved within the code by using the `@Fork` annotation.
9+
10+
## Important Notes on Using JMH with GraalVM Native Image
11+
12+
To make a JMH benchmark run as a native image, you can not fork the benchmark process in the same way as JMH does when running on the JVM.
13+
When running on HotSpot, JMH will fork a new JVM for each benchmark to ensure there is no interference in the measurements for each benchmark.
14+
This forking process is not possible with GraalVM Native Image and you should consider the following guidance when building JMH benchmarks that are meant to be run as native executables:
15+
* You should only include a single benchmark in each native executable.
16+
* You need to annotate the benchmark with `@Fork(0)` to ensure that the benchmark is not forked.
17+
* If you want to profile the benchmark to generate an optimized version of it, you should, obviously, ignore the benchmark results whilst profiling.
18+
19+
## Preparation
20+
21+
1. Download and install the GraalVM JDK using [SDKMAN!](https://sdkman.io/). For other installation options, visit the [Downloads page](https://www.graalvm.org/downloads/).
22+
```bash
23+
sdk install java 21.0.5-graal
24+
```
25+
26+
2. Download or clone the repository and navigate into the _/native-image/benchmark/jmh/binary-tree_ directory:
27+
```bash
28+
git clone https://github.com/graalvm/graalvm-demos
29+
```
30+
```bash
31+
cd graalvm-demos/native-image/benchmark/jmh/binary-tree
32+
```
33+
34+
## Build and Run the Benchmark on HotSpot
35+
36+
To build and run the benchmark on HotSpot, run the following Maven command:
37+
```shell
38+
./mvnw clean package exec:exec
39+
```
40+
41+
Note that within the _pom.xml_ file there are instructions to explicitly turn off the Graal JIT compiler using the option `-XX:-UseJVMCICompiler`.
42+
This means that benchmark will run using the C2 JIT compiler.
43+
44+
The application runs the benchmark and displays the results to the terminal.
45+
**The final result is the most significant.**
46+
You should see the result similar to this:
47+
```shell
48+
Benchmark (binaryTreesN) Mode Cnt Score Error Units
49+
BinaryTrees.bench 14 thrpt 6 348.923 ± 21.343 ops/s
50+
```
51+
52+
## Build and Run the Benchmark from a Native Executable
53+
54+
Now build a native executable using Native Image.
55+
This demo uses Oracle GraalVM Native Image, however, if you are using GraalVM Community, you may see lower figures for throughput.
56+
57+
1. Build a native executable, run the following command:
58+
```shell
59+
./mvnw package -Pnative
60+
```
61+
2. Run the benchmark from a native executable:
62+
```shell
63+
./target/benchmark-binary-tree
64+
```
65+
You should see similar results:
66+
```shell
67+
Benchmark (binaryTreesN) Mode Cnt Score Error Units
68+
BinaryTrees.bench 14 thrpt 6 282.335 ± 5.644 ops/s
69+
```
70+
71+
## Optimize the Benchmark for Throughput
72+
73+
You can improve the performance of this benchmark by applying [Profile-Guided Optimization (PGO)](https://www.graalvm.org/reference-manual/native-image/optimizations-and-performance/PGO/).
74+
75+
> PGO is available with Oracle GraalVM Native Image.
76+
77+
First, you will need to build an instrumented version of this native benchmark that contains extra code to trace the execution of the program and to profile it.
78+
Therefore, it will run slower than the previous version.
79+
After execution finishes, a profile file, _default.iprof_, is generated in the root directory.
80+
This file contains profiling information about the application and will be used to build a more efficient native executable.
81+
82+
1. To build the instrumented version of the native executable, run the following command:
83+
```shell
84+
./mvnw package -Pinstrumented
85+
```
86+
87+
2. Then run it to generate the profile file:
88+
```shell
89+
./target/benchmark-binary-tree-instr
90+
```
91+
92+
3. Now that you have the profiles, build and run the optimized version of this native benchmark:
93+
```shell
94+
./mvnw package -Poptimised
95+
```
96+
```shell
97+
./target/benchmark-binary-tree-opt
98+
```
99+
You should see similar results:
100+
```shell
101+
Benchmark (binaryTreesN) Mode Cnt Score Error Units
102+
BinaryTrees.bench 14 thrpt 6 311.630 ± 3.630 ops/s
103+
```
104+
105+
## Your Mileage May Vary
106+
107+
The results you see will vary depending on the hardware you are running on.
108+
The results above are from a 2019 MacBook Pro, i7, 32 GB RAM running on Oracle GraalVM for JDK 21.0.5.

0 commit comments

Comments
 (0)