【问题标题】:Using jmh to benchmark code without creating separate maven project使用 jmh 对代码进行基准测试而不创建单独的 maven 项目
【发布时间】:2016-08-10 18:24:54
【问题描述】:

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

【问题讨论】:

    标签: java maven benchmarking jmh


    【解决方案1】:

    简短的回答是是的

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

    +- src/
       +- main/java   - sources
       +- test/
          +- java        - test sources
          +- perf        - benchmarks
    

    你需要几个插件来实现。

    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>
    
    1. maven-compiler-plugintest-compile 阶段运行 jmh-generator-annprocess 注释处理器
    <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>
    
    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>
    
    <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>
    

    之后,您将获得一个带有基准的可执行 jar,可以像往常一样运行

    java -jar target/your-project-version-perf-tests.jar
    

    您可以查看工作示例here

    注意

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

    【讨论】:

    • 在您的工作示例中(即 ExampleBenchmark.java 中的 doSomethingTest),最好避免使用 for 循环,因为 JVM 中的循环优化会导致意外的性能结果。
    • 除了src/test/java 之外还有src/test/perf 有点不一致,因为后者通过技术(在本例中为java)来区分工件,而前者通过目的(perf)来区分它。由于基准测试可能也是用 Java 编写的,所以我更喜欢 src/perf/java,正如这篇关于 setting up JMH with Gradle 的文章中所建议的那样。
    • &lt;assembly&gt; 元素去哪儿了?我在您的工作示例的 pom.xml 中没有看到它
    • 哦,我在src/main/assembly/perf-tests.xml看到了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-17
    • 1970-01-01
    • 1970-01-01
    • 2022-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多