使用jmh来编写代码,而无需创建单独的maven项目

JSC*_*JSC 6 java benchmarking maven jmh

我正在开发一个Maven项目,我希望用jmh来测试我的代码.我想组织我的项目,使其包含源代码,单元测试和基准测试.似乎有一种方法可以在不创建单独的gradle项目的情况下对代码进行基准测试(请参阅链接).有没有办法在Maven做到这一点?

vsm*_*kov 7

简短的回答是肯定的.

我在我的项目中遇到过这个目录布局(但你绝对可以改变它)

+- src/
   +- main/java   - sources
   +- test/
      +- java        - test sources
      +- perf        - benchmarks
Run Code Online (Sandbox Code Playgroud)

你需要一些插件来实现这一目标.

  1. build-helper-maven-plugin 附加自定义测试源位置
<execution>
    <id>add-test-source</id>
    <phase>generate-test-sources</phase>
    <goals>
        <goal>add-test-source</goal>
    </goals>
    <configuration>
        <sources>
            <source>src/test/perf</source>
        </sources>
    </configuration>
</execution>
Run Code Online (Sandbox Code Playgroud)
  1. maven-compiler-pluginjmh-generator-annprocesstest-compile阶段运行注释处理器
<execution>
    <goals>
        <goal>testCompile</goal>
    </goals>

    <configuration>
        <annotationProcessorPaths>
            <path>
                <groupId>org.openjdk.jmh</groupId>
                <artifactId>jmh-generator-annprocess</artifactId>
                <version>${jmh.version}</version>
            </path>
        </annotationProcessorPaths>
    </configuration>
</execution>
Run Code Online (Sandbox Code Playgroud)
  1. maven-assembly-plugin 用基准创建可运行的jar
<execution>
    <id>make-assembly</id>
    <phase>package</phase>
    <goals>
        <goal>single</goal>
    </goals>
    <configuration>
        <attach>true</attach>
        <archive>
            <manifest>
                <mainClass>org.openjdk.jmh.Main</mainClass>
            </manifest>
        </archive>
    </configuration>
</execution>
Run Code Online (Sandbox Code Playgroud)
<assembly>
    <id>perf-tests</id>
    <formats>
        <format>jar</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <dependencySets>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <unpack>true</unpack>
            <scope>test</scope>
        </dependencySet>
    </dependencySets>
    <fileSets>
        <fileSet>
            <directory>${project.build.directory}/test-classes</directory>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>**/*</include>
            </includes>
            <useDefaultExcludes>true</useDefaultExcludes>
        </fileSet>
    </fileSets>
</assembly>
Run Code Online (Sandbox Code Playgroud)

之后你会得到一个带有基准测试的可执行jar,它可以像往常一样运行

java -jar target/your-project-version-perf-tests.jar
Run Code Online (Sandbox Code Playgroud)

你可以在这里看到工作示例.

注意

这个解决方案的唯一缺点是所有测试类和测试依赖项也将包含在带有基准测试的jar中,这些基准测试肯定会增加它.但是你可以通过在单独的(除了${project.build.directory}/test-classes)目录中编译基准来避免它.

  • 除了`src/test/java`之外,`src/test/perf`有点不一致,因为后者通过技术(在这种情况下为java)来区分工件,前者通过目的(perf)区分它.由于基准测试可能也是用Java编写的,我更喜欢`src/perf/java`,正如本文中关于[使用Gradle设置JMH]的建议(http://gvsmirnov.ru/blog/tech/2014/03) /10/keeping-your-benchmarks-separate.html). (2认同)