当前位置: 首页 > 知识库问答 >
问题:

如何在Maven中使用exec:java而不是exec:exec运行JMH基准测试?

卞昀
2023-03-14

javapapers.com上的这篇文章展示了如何通过键入mvn exec: exec在Maven中运行JMH基准测试。在Maven中运行JMH非常方便,因为您可以从Eclipse Run配置甚至在Maven阶段轻松运行它。

然而,这种设置有两个问题:

> < li>

当您杀死Maven时,JMH将继续在后台运行,因为< code>exec:exec在一个单独的虚拟机中启动它。

通常,JMH 将启动另一个 VM 来运行基准测试,因此你最终将同时运行至少 3 个 VM。

幸运的是,Exec Maven插件带有第二个目标,< code>exec:java,它直接在VM Maven运行时执行一个主类。然而,当我尝试使用< code>exec:java将Maven配置为运行JMH时,由于缺少类,基准测试崩溃了:

# 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>

以下是< code>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>

以下是我如何从我的< code >运行JMH。基准:

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

我意识到JMH使用了java.class。pathsystem属性来确定分叉VM的类路径,并且此属性不包含Maven的项目依赖项。但是,处理这个问题的首选方法是什么?

共有2个答案

壤驷心思
2023-03-14

解决此问题的一种方法是从 my 的类装入器中提取“有效”类路径从我的主要方法调用JMH之前的基准测试类:

URLClassLoader classLoader = (URLClassLoader) my.Benchmark.class.getClassLoader();
StringBuilder classpath = new StringBuilder();
for(URL url : classLoader.getURLs())
    classpath.append(url.getPath()).append(File.pathSeparator);
System.setProperty("java.class.path", classpath.toString());

这似乎有效,但感觉很像一个不必要的黑客…

钱飞翼
2023-03-14

虽然我之前的回答需要修改基准程序,但这里有一个仅限POM的解决方案,它在Dependency Plugin的帮助下将java.class.path系统属性设置为runtime类路径:

<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>
 类似资料:
  • 在我的场景中,基准测试中的方法应该在一个线程中按顺序运行并按顺序修改状态。 例如,有一个

  • 我使用 jmh(http://openjdk.java.net/projects/code 工具/jmh/ ) 来基准测试一些方法。此外,我有一组参数,我想用它们作为参数来运行此方法。是否可以为每个特定参数值生成一个方法(带有@GenerateMicroBenchmark注释)? 现在我使用类似的实现,但不太方便,因为我必须手动编写很多统一的代码:

  • 我想开始看看JMH,由于某些原因,我无法运行基准测试。让我解释一下我尝试过什么: 下载了一些官方的JMH示例。作为例子,我选择了非常简单,是一个很好的起点:http://hg.openjdk.java.net/code-tools/jmh/file/0c58dc4fcf17/jmh-samples/src/main/java/org/openjdk/jmh/samples/JMHSample_01

  • 我正在使用JMH,一个OpenJDK微基准测试工具。构建过程创建<代码>微基准。我用调用并传递jar名称和JMH参数的jar。 我想知道我们应该使用选项运行基准测试吗?为什么? 换句话说,我是否应该使用以下命令运行基准测试:

  • 我有几个用@Benchmark注释的大型基准类。在使用基准构建jar后,我可以使用以下命令运行所有这些类 如果我不想运行所有基准测试,如何指定要运行的基准测试?

  • 我通过JMH进行了一些基准测试 假设我在一个Java文件中列出了三个基准测试 每种方法都对服务于相同目的的不同算法进行基准测试。当我一起运行所有基准测试时,与逐个运行基准测试相比,结果会有所不同。 例如,在Java文件上仅使用onw基准执行JMH运行。 如果只运行此方法,此方法的结果会更好,但是如果使用更多基准,结果会更差。 假设基于结果的基准测试 我还尝试改变基准的顺序(按字典顺序执行),结果是