Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Run a JMH Benchmark in Maven Using exec:java Instead of exec:exec?

Tags:

java

maven

jmh

This post on javapapers.com shows how to run a JMH benchmark in Maven by typing mvn exec:exec. Running JMH within Maven is pretty handy, since you can easily run it from an Eclipse Run Configuration or even in a Maven phase.

However, there are two problems with this setup:

  1. When you kill Maven, JMH will continue running in the background, as exec:exec starts it in a separate VM.

  2. Usually, JMH will start yet another VM to run the benchmarks, so you will end up with at least 3 VMs running at the same time.

Fortunately, the Exec Maven Plugin comes with a second goal, exec:java, which executes a main class directly in the VM Maven runs. However, when I tried to configure Maven to run JMH using exec:java, the benchmark crashes because of missing classes:

# JMH 1.11.3 (released 40 days ago)
# VM version: Error: Could not find or load main class org.openjdk.jmh.runner.VersionMain
# VM invoker: C:\Program Files\Java\jdk1.7.0\jre\bin\java.exe
[...]
# Run progress: 0.00% complete, ETA 00:02:40
# Fork: 1 of 1
Error: Could not find or load main class org.openjdk.jmh.runner.ForkedMain
<forked VM failed with exit code 1>

Here is the relevant part of the pom.xml:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>1.4.0</version>
    <configuration>
        <mainClass>my.Benchmark</mainClass>
    </configuration>
</plugin>

And here is how I run JMH from my.Benchmark:

public static void main(String[] args) throws RunnerException {
    Options options = new OptionsBuilder().include(my.Benchmark.class.getSimpleName())
            .forks(1).build();
    new Runner(options).run();
}

I realize that JMH uses the java.class.path system property to determine the classpath for the forked VMs and that this property does not contain Maven's project dependencies. But what is the preferred way to deal with this?

like image 272
rolve Avatar asked Feb 23 '16 10:02

rolve


People also ask

How do you run a JMH benchmark?

There are two ways to run the JMH benchmark, uses Maven or run it via a JMH Runner class directly. 3.1 Maven, package it as a JAR and run it via org. openjdk. jmh.

What is Mvn exec Java?

mvn exec:java is a goal from the exec plugin for maven. It lets you specify a main class to execute (see pom. xml). This lets you avoid having to figure out the proper java command to run and classpath arguments and the like.

What is JMH in Java?

JMH is a Java harness for building, running, and analysing nano/micro/milli/macro benchmarks written in Java and other languages targetting the JVM.

What is maven Exec plugin?

Maven exec plugin allows us to execute system and Java programs from the maven command. There are two goals of the maven exec plugin: exec:exec - can be used to execute any program in a separate process. exec:java - can be used to run a Java program in the same VM.


1 Answers

While my previous answer requires modifying the benchmark program, here is a POM-only solution that sets the java.class.path system property to the runtime classpath with the help of the Dependency Plugin:

<plugin>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>build-classpath</id>
            <goals>
                <goal>build-classpath</goal>
            </goals>
            <configuration>
                <includeScope>runtime</includeScope>
                <outputProperty>depClasspath</outputProperty>
            </configuration>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <configuration>
        <mainClass>my.Benchmark</mainClass>
        <systemProperties>
            <systemProperty>
                <key>java.class.path</key>
                <value>${project.build.outputDirectory}${path.separator}${depClasspath}</value>
            </systemProperty>
        </systemProperties>
    </configuration>
</plugin>
like image 64
rolve Avatar answered Oct 20 '22 00:10

rolve