├── .github ├── release-drafter.yml └── workflows │ └── ci.yml ├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── LICENSE.txt ├── README.md ├── ide ├── README.md ├── eclipse-formatting.xml └── springdata.importorder ├── microbenchmark-runner-core ├── pom.xml └── src │ ├── main │ └── java │ │ └── jmh │ │ └── mbr │ │ └── core │ │ ├── BenchmarkConfigProperties.java │ │ ├── BenchmarkConfiguration.java │ │ ├── CompositeResultsWriter.java │ │ ├── Environment.java │ │ ├── EnvironmentBenchmarkConfiguration.java │ │ ├── JmhSupport.java │ │ ├── ResultsWriter.java │ │ ├── ResultsWriterFactory.java │ │ ├── StringUtils.java │ │ └── model │ │ ├── BenchmarkClass.java │ │ ├── BenchmarkDescriptor.java │ │ ├── BenchmarkDescriptorFactory.java │ │ ├── BenchmarkFixture.java │ │ ├── BenchmarkMethod.java │ │ ├── BenchmarkParameters.java │ │ ├── BenchmarkResults.java │ │ ├── HierarchicalBenchmarkDescriptor.java │ │ ├── MethodAware.java │ │ ├── ParametrizedBenchmarkMethod.java │ │ └── StateClass.java │ └── test │ ├── java │ └── jmh │ │ └── mbr │ │ └── core │ │ ├── JmhSupportUnitTests.java │ │ ├── ResultsWriterFactoryTests.java │ │ ├── TestResultsWriterFactory.java │ │ └── model │ │ └── BenchmarkDescriptorFactoryUnitTests.java │ └── resources │ └── META-INF │ └── services │ └── jmh.mbr.core.ResultsWriterFactory ├── microbenchmark-runner-extras ├── pom.xml └── src │ ├── main │ ├── java │ │ └── jmh │ │ │ └── mbr │ │ │ └── extras │ │ │ └── writer │ │ │ ├── CsvResultsFormatter.java │ │ │ ├── CsvResultsWriter.java │ │ │ ├── CsvResultsWriterFactory.java │ │ │ ├── ElasticsearchResultsWriter.java │ │ │ ├── ElasticserachResultsWriterFactory.java │ │ │ ├── JsonResultsFormatter.java │ │ │ ├── StackTraceCapture.java │ │ │ ├── SysoutCsvResultsWriter.java │ │ │ └── SysoutCsvResultsWriterFactory.java │ └── resources │ │ └── META-INF │ │ └── services │ │ └── jmh.mbr.core.ResultsWriterFactory │ └── test │ └── java │ └── jmh │ └── mbr │ └── extras │ ├── RunResultGenerator.java │ └── writer │ ├── CsvResultsWriterFactoryTests.java │ ├── ElasticsearchResultsWriterFactoryTests.java │ ├── ElasticsearchResultsWriterUnitTests.java │ ├── JsonResultsFormatterUnitTests.java │ └── SysoutResultsWriterFactoryTests.java ├── microbenchmark-runner-junit4 ├── pom.xml └── src │ ├── main │ └── java │ │ └── jmh │ │ └── mbr │ │ └── junit4 │ │ └── Microbenchmark.java │ └── test │ └── java │ └── jmh │ └── mbr │ └── junit4 │ ├── MicrobenchmarkUnitTests.java │ ├── ParametrizedBenchmark.java │ ├── PartiallyParametrizedBenchmark.java │ └── SimpleBenchmark.java ├── microbenchmark-runner-junit5-smoke-tests ├── pom.xml └── src │ └── test │ └── java │ └── jmh │ └── mbr │ └── junit5 │ ├── InnerStateSmokeTests.java │ └── ResultsWriterSmokeTests.java ├── microbenchmark-runner-junit5 ├── pom.xml └── src │ ├── main │ ├── java │ │ └── jmh │ │ │ └── mbr │ │ │ └── junit5 │ │ │ ├── Microbenchmark.java │ │ │ ├── MicrobenchmarkEngine.java │ │ │ ├── MicrobenchmarkEngineDescriptor.java │ │ │ ├── descriptor │ │ │ ├── AbstractBenchmarkDescriptor.java │ │ │ ├── AbstractExtensionContext.java │ │ │ ├── BenchmarkClassDescriptor.java │ │ │ ├── BenchmarkClassExtensionContext.java │ │ │ ├── BenchmarkFixtureDescriptor.java │ │ │ ├── BenchmarkMethodDescriptor.java │ │ │ ├── BenchmarkMethodExtensionContext.java │ │ │ ├── DescriptorUtils.java │ │ │ ├── ExtensionUtils.java │ │ │ └── ParametrizedBenchmarkMethodDescriptor.java │ │ │ ├── discovery │ │ │ ├── BenchmarkContainerResolver.java │ │ │ ├── BenchmarkFixtureResolver.java │ │ │ ├── BenchmarkMethodResolver.java │ │ │ ├── DiscoveryFilterApplier.java │ │ │ ├── DiscoverySelectorResolver.java │ │ │ ├── ElementResolver.java │ │ │ ├── ElementResolvers.java │ │ │ ├── JavaElementsResolver.java │ │ │ └── predicates │ │ │ │ ├── IsBenchmarkClass.java │ │ │ │ └── IsBenchmarkMethod.java │ │ │ └── execution │ │ │ ├── ConditionEvaluator.java │ │ │ ├── ConfigurationParameterBenchmarkConfiguration.java │ │ │ ├── ExtensionContextProvider.java │ │ │ └── JmhRunner.java │ └── resources │ │ └── META-INF │ │ └── services │ │ └── org.junit.platform.engine.TestEngine │ └── test │ └── java │ └── jmh │ └── mbr │ └── junit5 │ ├── JmhRunnerStub.java │ ├── JmhSupportStub.java │ ├── ParametrizedBenchmark.java │ ├── PartiallyParametrizedBenchmark.java │ ├── descriptor │ └── BenchmarkClassDescriptorUnitTests.java │ ├── discovery │ ├── JavaElementsResolverUnitTests.java │ └── predicates │ │ └── IsBenchmarkClassUnitTests.java │ └── execution │ ├── ConditionEvaluatorUnitTests.java │ └── JmhRunnerUnitTests.java ├── mvnw ├── mvnw.cmd ├── pom.xml └── src └── main └── resources └── start-benchmark.png /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | template: | 2 | ## What’s Changed 3 | 4 | $CHANGES 5 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | pull_request: 4 | branches: 5 | - main 6 | push: 7 | paths-ignore: 8 | - '**.md' 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | strategy: 14 | matrix: 15 | java: [ '17' ] 16 | architecture: [ 'x64' ] 17 | name: Build with JDK ${{ matrix.java }} on ${{ matrix.architecture }} 18 | steps: 19 | - uses: actions/checkout@v4.2.2 20 | - name: Setup JDK ${{ matrix.java }} 21 | uses: actions/setup-java@v4.7.1 22 | with: 23 | java-version: ${{ matrix.java }} 24 | architecture: ${{ matrix.architecture }} 25 | distribution: 'zulu' 26 | cache: 'maven' 27 | 28 | - name: Build with Maven 29 | run: ./mvnw --batch-mode verify 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### JetBrains template 3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 4 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 5 | 6 | # User-specific stuff 7 | .idea/ 8 | .vscode/ 9 | 10 | # CMake 11 | cmake-build-*/ 12 | 13 | # Mongo Explorer plugin 14 | .idea/**/mongoSettings.xml 15 | 16 | # File-based project format 17 | *.iws 18 | *.iml 19 | 20 | # IntelliJ 21 | out/ 22 | 23 | # mpeltonen/sbt-idea plugin 24 | .idea_modules/ 25 | 26 | # JIRA plugin 27 | atlassian-ide-plugin.xml 28 | 29 | # Cursive Clojure plugin 30 | .idea/replstate.xml 31 | 32 | # Crashlytics plugin (for Android Studio and IntelliJ) 33 | com_crashlytics_export_strings.xml 34 | crashlytics.properties 35 | crashlytics-build.properties 36 | fabric.properties 37 | 38 | # Editor-based Rest Client 39 | .idea/httpRequests 40 | ### Eclipse template 41 | 42 | .metadata 43 | bin/ 44 | tmp/ 45 | *.tmp 46 | *.bak 47 | *.swp 48 | *~.nib 49 | local.properties 50 | .settings/ 51 | .project 52 | .classpath 53 | .loadpath 54 | .recommenders 55 | 56 | # External tool builders 57 | .externalToolBuilders/ 58 | 59 | # Locally stored "Eclipse launch configurations" 60 | *.launch 61 | 62 | # PyDev specific (Python IDE for Eclipse) 63 | *.pydevproject 64 | 65 | # CDT-specific (C/C++ Development Tooling) 66 | .cproject 67 | 68 | # CDT- autotools 69 | .autotools 70 | 71 | # Java annotation processor (APT) 72 | .factorypath 73 | 74 | # PDT-specific (PHP Development Tools) 75 | .buildpath 76 | 77 | # sbteclipse plugin 78 | .target 79 | 80 | # Tern plugin 81 | .tern-project 82 | 83 | # TeXlipse plugin 84 | .texlipse 85 | 86 | # STS (Spring Tool Suite) 87 | .springBeans 88 | 89 | # Code Recommenders 90 | .recommenders/ 91 | 92 | # Annotation Processing 93 | .apt_generated/ 94 | 95 | # Scala IDE specific (Scala & Java development for Eclipse) 96 | .cache-main 97 | .scala_dependencies 98 | .worksheet 99 | ### Maven template 100 | target/ 101 | pom.xml.tag 102 | pom.xml.releaseBackup 103 | pom.xml.versionsBackup 104 | pom.xml.next 105 | release.properties 106 | dependency-reduced-pom.xml 107 | buildNumber.properties 108 | .mvn/timing.properties 109 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mp911de/microbenchmark-runner/233b7b3293bd1bca8e9dd4189883befb1bfebf99/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip 2 | 3 | -------------------------------------------------------------------------------- /ide/README.md: -------------------------------------------------------------------------------- 1 | # Spring Data Code Formatting Settings 2 | 3 | This directory contains `eclipse-formatting.xml` and `springdata.importorder` settings files to be used with Eclipse and IntelliJ. 4 | 5 | ## Eclipse Setup 6 | 7 | Import both files in Eclipse through the Preferences dialog. 8 | 9 | ## IntelliJ Setup 10 | 11 | Use the IntelliJ [Eclipse Code Formatter](https://plugins.jetbrains.com/plugin/6546-eclipse-code-formatter) plugin to configure code formatting and import ordering with the newest Eclipse formatter version. 12 | 13 | Additionally, make sure to configure your import settings in `Editor -> Code Style -> Java` with the following explicit settings: 14 | 15 | * Use tab character indents 16 | * Class count to use import with `*`: 10 17 | * Names count to use static import with `*`: 1 18 | -------------------------------------------------------------------------------- /ide/springdata.importorder: -------------------------------------------------------------------------------- 1 | #Organize Import Order 2 | #Mon Nov 14 09:58:12 CET 2016 3 | 5=com 4 | 4=org 5 | 3=javax 6 | 2=java 7 | 1= 8 | 0=\# 9 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | com.github.mp911de.microbenchmark-runner 9 | microbenchmark-runner-parent 10 | 0.6.0.BUILD-SNAPSHOT 11 | 12 | 13 | microbenchmark-runner-core 14 | 15 | 16 | 17 | 18 | org.openjdk.jmh 19 | jmh-core 20 | 21 | 22 | 23 | org.junit.jupiter 24 | junit-jupiter-api 25 | test 26 | 27 | 28 | 29 | org.junit.jupiter 30 | junit-jupiter-engine 31 | test 32 | 33 | 34 | 35 | org.assertj 36 | assertj-core 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/main/java/jmh/mbr/core/BenchmarkConfigProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2020 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * https://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core; 11 | 12 | import java.time.Duration; 13 | import java.util.Arrays; 14 | import java.util.Iterator; 15 | import java.util.List; 16 | 17 | /** 18 | * Collection of {@link ConfigProperty configuration properties}. 19 | */ 20 | public interface BenchmarkConfigProperties { 21 | 22 | String PREFIX = "jmh.mbr."; 23 | 24 | ConfigProperty ENABLED = new ConfigProperty<>(true, PREFIX + "enabled"); 25 | 26 | ConfigProperty PROJECT = new ConfigProperty<>(null, PREFIX + "project"); 27 | ConfigProperty VERSION = new ConfigProperty<>(null, PREFIX + "project.version"); 28 | ConfigProperty PUBLISH_URI = new ConfigProperty<>(null, PREFIX + "report.publishTo"); 29 | ConfigProperty BENCHMARK_REPORT_DIR = new ConfigProperty<>(null, PREFIX + "report.dir"); 30 | 31 | ConfigProperty WARMUP_ITERATIONS = new ConfigProperty<>(-1, PREFIX + "warmup.iterations", "wi"); 32 | ConfigProperty WARMUP_BATCH_SIZE = new ConfigProperty<>(-1, PREFIX + "warmup.batchSize", "wbs"); 33 | ConfigProperty WARMUP_TIME = new ConfigProperty<>(Duration.ZERO, PREFIX + "warmup.time", "w"); 34 | ConfigProperty WARMUP_MODE = new ConfigProperty<>(null, PREFIX + "warmup.mode", "wm"); 35 | 36 | ConfigProperty MEASUREMENT_ITERATIONS = new ConfigProperty<>(-1, PREFIX + "measurement.iterations", "i"); 37 | ConfigProperty MEASUREMENT_BATCH_SIZE = new ConfigProperty<>(-1, PREFIX + "measurement.batchSize", "bs"); 38 | ConfigProperty MEASUREMENT_TIME = new ConfigProperty<>(Duration.ZERO, PREFIX + "measurement.time", "r"); 39 | 40 | ConfigProperty MODE = new ConfigProperty<>(null, PREFIX + "mode", "bm"); 41 | ConfigProperty TIMEOUT = new ConfigProperty<>(Duration.ZERO, PREFIX + "timeout", "to"); 42 | 43 | ConfigProperty FORKS = new ConfigProperty<>(-1, PREFIX + "forks", "f"); 44 | 45 | /** 46 | * Return a {@link Iterator} over all {@link ConfigProperty properties}. 47 | * 48 | * @return a {@link List} over all {@link ConfigProperty properties}. 49 | */ 50 | static Iterator> iterator() { 51 | return asList().iterator(); 52 | } 53 | 54 | /** 55 | * Return a {@link List} of all {@link ConfigProperty properties}. 56 | * 57 | * @return a {@link List} of all {@link ConfigProperty properties}. 58 | */ 59 | static List> asList() { 60 | return Arrays 61 | .asList(ENABLED, PROJECT, VERSION, PUBLISH_URI, BENCHMARK_REPORT_DIR, WARMUP_ITERATIONS, WARMUP_BATCH_SIZE, WARMUP_TIME, WARMUP_MODE, MEASUREMENT_ITERATIONS, MEASUREMENT_TIME, MEASUREMENT_BATCH_SIZE, MODE, TIMEOUT, FORKS); 62 | } 63 | 64 | class ConfigProperty { 65 | 66 | private final String[] properties; 67 | private final T defaultValue; 68 | 69 | ConfigProperty(T defaultValue, String... properties) { 70 | 71 | this.properties = properties; 72 | this.defaultValue = defaultValue; 73 | } 74 | 75 | public String propertyName() { 76 | return propertyNames()[0]; 77 | } 78 | 79 | public String[] propertyNames() { 80 | return properties; 81 | } 82 | 83 | public T defaultValue() { 84 | return defaultValue; 85 | } 86 | 87 | @SuppressWarnings("unchecked") 88 | Class getType() { 89 | return defaultValue != null ? (Class) defaultValue 90 | .getClass() : (Class) Object.class; 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/main/java/jmh/mbr/core/BenchmarkConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2020 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * https://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core; 11 | 12 | import java.time.Duration; 13 | import java.util.Map; 14 | 15 | import org.openjdk.jmh.annotations.Mode; 16 | 17 | /** 18 | * Configuration properties to run a JMH benchmark. 19 | */ 20 | public interface BenchmarkConfiguration { 21 | 22 | /** 23 | * Read {@code benchmarksEnabled} property from {@link jmh.mbr.core.Environment}. 24 | * 25 | * @return true if not set. 26 | */ 27 | default boolean isEnabled() { 28 | return true; 29 | } 30 | 31 | /** 32 | * @return measurement mode, see {@link Mode}. 33 | */ 34 | String getMode(); 35 | 36 | static BenchmarkConfiguration defaultOptions() { 37 | return EnvironmentBenchmarkConfiguration.INSTANCE; 38 | } 39 | 40 | default String publishUri() { 41 | return null; 42 | } 43 | 44 | /** 45 | * Read {@code warmupIterations} property from {@link jmh.mbr.core.Environment}. 46 | * 47 | * @return -1 if not set. 48 | */ 49 | int getWarmupIterations(); 50 | 51 | int getWarmupBatchSize(); 52 | 53 | /** 54 | * @return warmup measurement mode, see {@link Mode}. 55 | */ 56 | String getWarmupMode(); 57 | 58 | /** 59 | * Read {@code measurementIterations} property from {@link jmh.mbr.core.Environment}. 60 | * 61 | * @return -1 if not set. 62 | */ 63 | int getMeasurementIterations(); 64 | 65 | int getMeasurementBatchSize(); 66 | 67 | Duration getTimeout(); 68 | 69 | /** 70 | * Read {@code forks} property from {@link jmh.mbr.core.Environment}. 71 | * 72 | * @return -1 if not set. 73 | */ 74 | int getForksCount(); 75 | 76 | /** 77 | * Read {@code benchmarkReportDir} property from {@link jmh.mbr.core.Environment}. 78 | * 79 | * @return {@literal null} if not set. 80 | */ 81 | default String getReportDirectory() { 82 | return null; 83 | } 84 | 85 | /** 86 | * Read {@code measurementTime} property from {@link jmh.mbr.core.Environment}. 87 | * 88 | * @return {@link Duration#ZERO} if not set. 89 | */ 90 | Duration getMeasurementTime(); 91 | 92 | /** 93 | * Read {@code warmupTime} property from {@link jmh.mbr.core.Environment}. 94 | * 95 | * @return {@link Duration#ZERO} if not set. 96 | */ 97 | Duration getWarmupTime(); 98 | 99 | /** 100 | * Return all properties as {@link Map} using the configuration property name as key. 101 | * 102 | * @return the configuration property map. 103 | */ 104 | Map asMap(); 105 | } 106 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/main/java/jmh/mbr/core/CompositeResultsWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core; 11 | 12 | import java.util.List; 13 | 14 | import jmh.mbr.core.model.BenchmarkResults; 15 | import org.openjdk.jmh.runner.format.OutputFormat; 16 | 17 | /** 18 | * Composite {@link ResultsWriter}. 19 | */ 20 | class CompositeResultsWriter implements ResultsWriter { 21 | 22 | private final List writers; 23 | 24 | CompositeResultsWriter(List writers) { 25 | this.writers = writers; 26 | } 27 | 28 | @Override 29 | public void write(OutputFormat output, BenchmarkResults results) { 30 | for (ResultsWriter writer : writers) { 31 | writer.write(output, results); 32 | } 33 | } 34 | 35 | public void add(ResultsWriter writer) { 36 | if (writer != null) { 37 | this.writers.add(writer); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/main/java/jmh/mbr/core/Environment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core; 11 | 12 | import java.time.Duration; 13 | import java.util.Map; 14 | import java.util.Map.Entry; 15 | import java.util.Objects; 16 | import java.util.Properties; 17 | import java.util.function.Predicate; 18 | import java.util.stream.Collectors; 19 | 20 | import jmh.mbr.core.BenchmarkConfigProperties.ConfigProperty; 21 | 22 | /** 23 | * Utility to obtain property values from System properties and environment variables. 24 | */ 25 | public abstract class Environment { 26 | 27 | private static final Predicate> CONFIG_PROPERTY_FILTER = it -> it.getKey() 28 | .toString().startsWith(BenchmarkConfigProperties.PREFIX); 29 | 30 | /** 31 | * @return the {@literal os.name}. 32 | */ 33 | public static String getOsName() { 34 | return getProperty("os.name", "n/a"); 35 | } 36 | 37 | /** 38 | * @return a {@link Map} containing all configuration properties prefixed with {@link BenchmarkConfigProperties#PREFIX}. 39 | */ 40 | public static Map jmhConfigProperties() { 41 | 42 | Properties properties = new Properties(); 43 | properties.putAll(filter(System.getenv())); 44 | properties.putAll(filter(System.getProperties())); 45 | 46 | return properties.entrySet() 47 | .stream() 48 | .collect(Collectors.toMap(e -> e.getKey().toString(), e -> e.getValue())); 49 | } 50 | 51 | /** 52 | * Retrieve a property value by its {@code propertyName}. Attempts to read the property from system properties first 53 | * and then (if not set through system properties), from the environment variables. 54 | * 55 | * @param propertyName must not be {@literal null}. 56 | * @return the value or {@literal null} if not set. 57 | */ 58 | public static String getProperty(String propertyName) { 59 | 60 | Objects.requireNonNull(propertyName, "PropertyName must not be null!"); 61 | 62 | return obtainPropertyValue(new ConfigProperty<>(null, propertyName)); 63 | } 64 | 65 | /** 66 | * Get the value of the given {@link ConfigProperty} or its {@link ConfigProperty#defaultValue() default value}. 67 | * 68 | * @param configProperty must not be {@literal null}. 69 | * @param the properties target type. 70 | * @return {@literal null} when not set. 71 | * @throws NullPointerException if required {@literal configProperty} argument is {@literal null}. 72 | */ 73 | static T getPropertyOrDefault(ConfigProperty configProperty) { 74 | 75 | Objects.requireNonNull(configProperty, "ConfigProperty must not be null!"); 76 | 77 | String value = obtainPropertyValue(configProperty); 78 | 79 | if (StringUtils.isEmpty(value)) { 80 | return configProperty.defaultValue(); 81 | } 82 | 83 | Class targetType = configProperty.getType(); 84 | 85 | if (targetType == Boolean.class) { 86 | return targetType.cast(Boolean.valueOf(value)); 87 | } 88 | 89 | if (Long.class.isAssignableFrom(targetType)) { 90 | return targetType.cast(Long.parseLong(value)); 91 | } 92 | 93 | if (Duration.class.isAssignableFrom(targetType)) { 94 | return targetType.cast(Duration.ofSeconds(Long.parseLong(value))); 95 | } 96 | 97 | return targetType.cast(value); 98 | } 99 | 100 | private static Map filter(Map source) { 101 | 102 | return source.entrySet() 103 | .stream() 104 | .filter(CONFIG_PROPERTY_FILTER) 105 | .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); 106 | } 107 | 108 | private static String obtainPropertyValue(ConfigProperty configProperty) { 109 | 110 | for (String propertyName : configProperty.propertyNames()) { 111 | 112 | if (System.getProperties().containsKey(propertyName)) { 113 | return System.getProperty(propertyName); 114 | } 115 | 116 | if (System.getenv().containsKey(propertyName)) { 117 | return System.getenv(propertyName); 118 | } 119 | } 120 | 121 | return null; 122 | } 123 | 124 | /** 125 | * Retrieve a property value by its {@code propertyName}. Attempts to read the property from system properties first 126 | * and then (if not set through system properties), from the environment variables. Falls back to {@code defaultValue} 127 | * if the property is not set. 128 | * 129 | * @param propertyName must not be {@literal null}. 130 | * @param defaultValue must not be {@literal null}. 131 | * @return the value or {@literal null} if not set. 132 | */ 133 | public static String getProperty(String propertyName, String defaultValue) { 134 | 135 | Objects.requireNonNull(propertyName, "PropertyName must not be null!"); 136 | return obtainPropertyValue(new ConfigProperty<>(defaultValue, propertyName)); 137 | } 138 | 139 | /** 140 | * Check whether the property is configured (i.e. the property value is not empty and not {@literal null}). 141 | * 142 | * @param propertyName must not be {@literal null}. 143 | * @return {@literal true} if the environment contains a value for {@code propertyName}. 144 | */ 145 | public static boolean containsProperty(String propertyName) { 146 | return !StringUtils.isEmpty(getProperty(propertyName)); 147 | } 148 | 149 | private Environment() { 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/main/java/jmh/mbr/core/EnvironmentBenchmarkConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core; 11 | 12 | import java.time.Duration; 13 | import java.util.Map; 14 | import java.util.stream.Collectors; 15 | 16 | /** 17 | * {@link BenchmarkConfiguration} based on the {@link Environment}. 18 | * 19 | * @see Environment 20 | */ 21 | enum EnvironmentBenchmarkConfiguration implements BenchmarkConfiguration { 22 | 23 | INSTANCE; 24 | 25 | @Override 26 | public String getMode() { 27 | return Environment.getPropertyOrDefault(BenchmarkConfigProperties.MODE); 28 | } 29 | 30 | /** 31 | * Read {@code benchmarksEnabled} property from {@link Environment}. 32 | * 33 | * @return true if not set. 34 | */ 35 | public boolean isEnabled() { 36 | return Environment.getPropertyOrDefault(BenchmarkConfigProperties.ENABLED); 37 | } 38 | 39 | /** 40 | * Read {@code warmupIterations} property from {@link Environment}. 41 | * 42 | * @return -1 if not set. 43 | */ 44 | public int getWarmupIterations() { 45 | return Environment 46 | .getPropertyOrDefault(BenchmarkConfigProperties.WARMUP_ITERATIONS); 47 | } 48 | 49 | @Override 50 | public int getWarmupBatchSize() { 51 | return Environment 52 | .getPropertyOrDefault(BenchmarkConfigProperties.WARMUP_BATCH_SIZE); 53 | } 54 | 55 | @Override 56 | public String getWarmupMode() { 57 | return Environment 58 | .getPropertyOrDefault(BenchmarkConfigProperties.WARMUP_MODE); 59 | } 60 | 61 | /** 62 | * Read {@code measurementIterations} property from {@link Environment}. 63 | * 64 | * @return -1 if not set. 65 | */ 66 | public int getMeasurementIterations() { 67 | return Environment 68 | .getPropertyOrDefault(BenchmarkConfigProperties.MEASUREMENT_ITERATIONS); 69 | } 70 | 71 | @Override 72 | public int getMeasurementBatchSize() { 73 | return Environment 74 | .getPropertyOrDefault(BenchmarkConfigProperties.MEASUREMENT_ITERATIONS); 75 | } 76 | 77 | @Override 78 | public Duration getTimeout() { 79 | return Environment.getPropertyOrDefault(BenchmarkConfigProperties.TIMEOUT); 80 | } 81 | 82 | /** 83 | * Read {@code forks} property from {@link Environment}. 84 | * 85 | * @return -1 if not set. 86 | */ 87 | public int getForksCount() { 88 | return Environment.getPropertyOrDefault(BenchmarkConfigProperties.FORKS); 89 | } 90 | 91 | /** 92 | * Read {@code benchmarkReportDir} property from {@link Environment}. 93 | * 94 | * @return {@literal null} if not set. 95 | */ 96 | public String getReportDirectory() { 97 | return Environment 98 | .getPropertyOrDefault(BenchmarkConfigProperties.BENCHMARK_REPORT_DIR); 99 | } 100 | 101 | /** 102 | * Read {@code measurementTime} property from {@link Environment}. 103 | * 104 | * @return {@link Duration#ZERO} if not set. 105 | */ 106 | public Duration getMeasurementTime() { 107 | return Environment 108 | .getPropertyOrDefault(BenchmarkConfigProperties.MEASUREMENT_TIME); 109 | } 110 | 111 | /** 112 | * Read {@code warmupTime} property from {@link Environment}. 113 | * 114 | * @return {@link Duration#ZERO} if not set. 115 | */ 116 | public Duration getWarmupTime() { 117 | return Environment 118 | .getPropertyOrDefault(BenchmarkConfigProperties.WARMUP_TIME); 119 | } 120 | 121 | @Override 122 | public String publishUri() { 123 | return Environment 124 | .getPropertyOrDefault(BenchmarkConfigProperties.PUBLISH_URI); 125 | } 126 | 127 | @Override 128 | public Map asMap() { 129 | 130 | return Environment.jmhConfigProperties().entrySet() 131 | .stream() 132 | .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/main/java/jmh/mbr/core/ResultsWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | import java.util.ServiceLoader; 15 | 16 | import jmh.mbr.core.model.BenchmarkResults; 17 | import org.openjdk.jmh.results.RunResult; 18 | import org.openjdk.jmh.runner.format.OutputFormat; 19 | 20 | /** 21 | * Writes JMH results to an external target. This can be targets such as files, HTTP endpoints, or databases. {@link ResultsWriter} can be contributed through Java's {@link ServiceLoader} plugin mechanism. 22 | * 23 | * @see ResultsWriterFactory 24 | */ 25 | public interface ResultsWriter { 26 | 27 | /** 28 | * Write the {@link RunResult}s. 29 | * 30 | * @param output original {@link OutputFormat} to append further details or failures that occurred while writing results. 31 | * @param results can be {@literal null}. 32 | */ 33 | void write(OutputFormat output, BenchmarkResults results); 34 | 35 | 36 | /** 37 | * Creates a {@link ResultsWriter} given a {@code uri}. This method considers {@link ResultsWriter} plugins provided by {@link ResultsWriterFactory} via Java's {@link ServiceLoader} mechanism. Returns {@literal null} if no applicable {@link ResultsWriter} was found. 38 | * 39 | * @param uri 40 | * @return the {@link ResultsWriter} or {@literal null} if none was found or none was applicable to {@code uri}. 41 | */ 42 | static ResultsWriter forUri(String uri) { 43 | 44 | ServiceLoader loader = ServiceLoader.load(ResultsWriterFactory.class); 45 | 46 | List result = new ArrayList<>(); 47 | for (ResultsWriterFactory factory : loader) { 48 | ResultsWriter writer = factory.forUri(uri); 49 | if (writer != null) { 50 | result.add(writer); 51 | } 52 | } 53 | 54 | return result.isEmpty() ? null : new CompositeResultsWriter(result); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/main/java/jmh/mbr/core/ResultsWriterFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core; 11 | 12 | /** 13 | * SPI for {@link ResultsWriter} plugins. Uses an opaque {@code uri} to specify the desired target where results can be 14 | * written to. 15 | * 16 | * @see java.util.ServiceLoader 17 | */ 18 | public interface ResultsWriterFactory { 19 | 20 | /** 21 | * Creates a new {@link ResultsWriter} for {@code uri}. Implementations may return {@literal null} if the {@code uri} 22 | * is not supported. 23 | * 24 | * @param uri target location to which results are written to (may be null or empty). 25 | * @return the {@link ResultsWriter} implementation or {@literal null} if the {@code uri} is not supported. 26 | */ 27 | ResultsWriter forUri(String uri); 28 | } 29 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/main/java/jmh/mbr/core/StringUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core; 11 | 12 | import java.util.Collection; 13 | import java.util.Iterator; 14 | 15 | /** 16 | * Miscellaneous {@link String} utility methods. 17 | */ 18 | public class StringUtils { 19 | 20 | /** 21 | * Check whether the given {@link String} is empty. 22 | * 23 | * @param theString the candidate String 24 | * @return {@literal true} if the string is empty. 25 | */ 26 | public static boolean isEmpty(Object theString) { 27 | return (theString == null || "".equals(theString)); 28 | } 29 | 30 | /** 31 | * Check whether the given {@link String} contains actual text. 32 | * 33 | * @param theString the {@link String} to check (may be {@code null}) 34 | * @return {@code true} if the {@link String} is not {@code null}, its length is greater than 0, and it does not 35 | * contain whitespace only 36 | */ 37 | public static boolean hasText(String theString) { 38 | return (theString != null && !theString.isEmpty() && containsText(theString)); 39 | } 40 | 41 | private static boolean containsText(CharSequence str) { 42 | 43 | int length = str.length(); 44 | 45 | for (int i = 0; i < length; i++) { 46 | if (!Character.isWhitespace(str.charAt(i))) { 47 | return true; 48 | } 49 | } 50 | return false; 51 | } 52 | 53 | /** 54 | * Convert a {@link Collection} into a delimited {@link String} (e.g. CSV). 55 | *

56 | * Useful for {@link #toString()} implementations. 57 | * 58 | * @param c the {@code Collection} to convert (potentially {@code null} or empty). 59 | * @param delim the delimiter to use (typically a ",") 60 | * @return the delimited {@link String} 61 | */ 62 | public static String collectionToDelimitedString(Collection c, String delim) { 63 | 64 | if (c.isEmpty()) { 65 | return ""; 66 | } 67 | 68 | StringBuilder sb = new StringBuilder(); 69 | Iterator it = c.iterator(); 70 | while (it.hasNext()) { 71 | sb.append(it.next()); 72 | if (it.hasNext()) { 73 | sb.append(delim); 74 | } 75 | } 76 | return sb.toString(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/main/java/jmh/mbr/core/model/BenchmarkClass.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core.model; 11 | 12 | import java.util.ArrayList; 13 | import java.util.Collection; 14 | import java.util.List; 15 | import java.util.Objects; 16 | 17 | /** 18 | * {@link BenchmarkDescriptor} for a single {@link Class benchmark class} along its children. 19 | * 20 | * @see BenchmarkMethod 21 | * @see HierarchicalBenchmarkDescriptor 22 | */ 23 | public class BenchmarkClass extends HierarchicalBenchmarkDescriptor { 24 | 25 | private BenchmarkClass(ClassDescriptor descriptor, List children) { 26 | super(descriptor, children); 27 | } 28 | 29 | /** 30 | * Create a new {@link BenchmarkClass} given {@link Class the benchmark class} and its children. 31 | * 32 | * @param benchmarkClass the actual {@link Class benchmark class} to inspect. 33 | * @param children child descriptors. 34 | * @return the {@link BenchmarkClass} descriptor. 35 | */ 36 | public static BenchmarkClass create(Class benchmarkClass, Collection children) { 37 | 38 | Objects.requireNonNull(benchmarkClass, "Benchmark class must not be null!"); 39 | Objects.requireNonNull(children, "Children must not be null!"); 40 | 41 | return new BenchmarkClass(new ClassDescriptor(benchmarkClass), new ArrayList<>(children)); 42 | } 43 | 44 | public Class getJavaClass() { 45 | return ((ClassDescriptor) getDescriptor()).benchmarkClass; 46 | } 47 | 48 | private static class ClassDescriptor implements BenchmarkDescriptor { 49 | 50 | private final Class benchmarkClass; 51 | 52 | private ClassDescriptor(Class benchmarkClass) { 53 | this.benchmarkClass = benchmarkClass; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/main/java/jmh/mbr/core/model/BenchmarkDescriptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core.model; 11 | 12 | /** 13 | * Marker interfaces for types implementing a benchmark component descriptor. 14 | * 15 | * @see BenchmarkClass 16 | * @see BenchmarkMethod 17 | * @see ParametrizedBenchmarkMethod 18 | * @see BenchmarkFixture 19 | */ 20 | public interface BenchmarkDescriptor {} 21 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/main/java/jmh/mbr/core/model/BenchmarkDescriptorFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core.model; 11 | 12 | import jmh.mbr.core.model.BenchmarkParameters.BenchmarkArgument; 13 | 14 | import java.lang.reflect.Method; 15 | import java.lang.reflect.Parameter; 16 | import java.util.ArrayList; 17 | import java.util.Arrays; 18 | import java.util.Collection; 19 | import java.util.Collections; 20 | import java.util.Iterator; 21 | import java.util.List; 22 | import java.util.Objects; 23 | import java.util.Optional; 24 | import java.util.function.Predicate; 25 | import java.util.stream.Collectors; 26 | import java.util.stream.Stream; 27 | 28 | import org.openjdk.jmh.annotations.Benchmark; 29 | 30 | /** 31 | * Factory to create a {@link BenchmarkDescriptor} from a benchmark class. 32 | */ 33 | public class BenchmarkDescriptorFactory { 34 | 35 | private final Class benchmarkClass; 36 | 37 | private BenchmarkDescriptorFactory(Class benchmarkClass) { 38 | this.benchmarkClass = benchmarkClass; 39 | } 40 | 41 | public static BenchmarkDescriptorFactory create(Class benchmarkClass) { 42 | 43 | Objects.requireNonNull(benchmarkClass, "Benchmark class must not be null"); 44 | 45 | return new BenchmarkDescriptorFactory(benchmarkClass); 46 | } 47 | 48 | /** 49 | * @return the {@link BenchmarkDescriptor} for the underlying {@link Class}. 50 | */ 51 | public BenchmarkClass createDescriptor() { 52 | 53 | List children = getBenchmarkMethods(it -> it.isAnnotationPresent(Benchmark.class)).map(it -> { 54 | 55 | if (it.isParametrized()) { 56 | 57 | List fixtures = createFixtures(it); 58 | 59 | return new ParametrizedBenchmarkMethod(it, fixtures); 60 | } 61 | 62 | return it; 63 | }).collect(Collectors.toList()); 64 | 65 | return BenchmarkClass.create(benchmarkClass, children); 66 | } 67 | 68 | /** 69 | * Creates {@link BenchmarkFixture} for a parametrized {@link BenchmarkMethod}. 70 | * 71 | * @param method the {@link BenchmarkMethod} to inspect. 72 | * @return list of fixtures if parameterized. Empty list if the method is not parametrized. 73 | */ 74 | public List createFixtures(BenchmarkMethod method) { 75 | 76 | List stateClasses = new ArrayList<>(); 77 | 78 | if (StateClass.isParametrized(method.getDeclaringClass())) { 79 | stateClasses.add(StateClass.create(method.getDeclaringClass())); 80 | } 81 | 82 | List argumentStateClasses = Arrays.stream(method.getParameters())// 83 | .map(Parameter::getType) // 84 | .filter(StateClass::isParametrized) // 85 | .map(StateClass::create) // 86 | .collect(Collectors.toList()); 87 | 88 | stateClasses.addAll(argumentStateClasses); 89 | 90 | Collection arguments = BenchmarkParameters.discover(stateClasses); 91 | Iterator iterator = arguments.iterator(); 92 | 93 | return iterator.hasNext() ? createFixtures(iterator.next(), iterator) : Collections.emptyList(); 94 | } 95 | 96 | private List createFixtures(BenchmarkArgument argument, Iterator iterator) { 97 | 98 | List fixtures = new ArrayList<>(argument.getParameterCount()); 99 | 100 | for (String parameter : argument.getParameters()) { 101 | fixtures.add(BenchmarkFixture.create(argument.getName(), parameter)); 102 | } 103 | 104 | while (iterator.hasNext()) { 105 | fixtures = enhance(fixtures, iterator.next()); 106 | } 107 | 108 | return fixtures; 109 | 110 | } 111 | 112 | private List enhance(List fixtures, BenchmarkArgument argument) { 113 | 114 | List enhanced = new ArrayList<>(fixtures.size() * argument.getParameterCount()); 115 | 116 | for (BenchmarkFixture fixture : fixtures) { 117 | 118 | for (String parameter : argument.getParameters()) { 119 | enhanced.add(fixture.enhance(argument.getName(), parameter)); 120 | } 121 | } 122 | 123 | return enhanced; 124 | } 125 | 126 | public Optional getBenchmarkMethod(String name, Class... parameterTypes) { 127 | 128 | return getBenchmarkMethods(it -> it.getName().equals(name) && it.getParameterCount() == parameterTypes.length 129 | && Arrays.equals(parameterTypes, it.getParameterTypes())).findFirst(); 130 | } 131 | 132 | public BenchmarkMethod getRequiredBenchmarkMethod(String name, Class... parameterTypes) { 133 | return getBenchmarkMethod(name, parameterTypes) 134 | .orElseThrow(() -> new IllegalArgumentException("Cannot find method " + name)); 135 | } 136 | 137 | private Stream getBenchmarkMethods(Predicate filter) { 138 | 139 | return Stream.concat(Arrays.stream(benchmarkClass.getMethods()), Arrays.stream(benchmarkClass.getDeclaredMethods())) // 140 | .filter(filter) // 141 | .distinct() // 142 | .map(BenchmarkMethod::new); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/main/java/jmh/mbr/core/model/BenchmarkFixture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core.model; 11 | 12 | 13 | import java.util.Collections; 14 | import java.util.LinkedHashMap; 15 | import java.util.Map; 16 | 17 | /** 18 | * Represents a parametrized fixture. 19 | */ 20 | public class BenchmarkFixture implements BenchmarkDescriptor { 21 | 22 | private final Map fixture; 23 | 24 | private BenchmarkFixture(Map fixture) { 25 | this.fixture = fixture; 26 | } 27 | 28 | /** 29 | * Create a {@link BenchmarkFixture}. 30 | * 31 | * @param name name of the fixture parameter. Typically a field name. 32 | * @param parameter value of the fixture parameter. 33 | * @return the {@link BenchmarkFixture}. 34 | * @see org.openjdk.jmh.annotations.Param 35 | */ 36 | public static BenchmarkFixture create(String name, String parameter) { 37 | return new BenchmarkFixture(Collections.singletonMap(name, parameter)); 38 | } 39 | 40 | /** 41 | * Create an enhanced {@link BenchmarkFixture} that contains all parameter values and the given parameter tuple. 42 | * 43 | * @param name name of the fixture parameter. Typically a field name. 44 | * @param parameter value of the fixture parameter. 45 | * @return the {@link BenchmarkFixture}. 46 | */ 47 | public BenchmarkFixture enhance(String name, String parameter) { 48 | 49 | Map fixture = new LinkedHashMap<>(this.fixture.size() + 1); 50 | fixture.putAll(this.fixture); 51 | fixture.put(name, parameter); 52 | 53 | return new BenchmarkFixture(fixture); 54 | } 55 | 56 | public Map getFixture() { 57 | return fixture; 58 | } 59 | 60 | public String getDisplayName() { 61 | 62 | String name = fixture.toString(); 63 | if (name.startsWith("{") && name.endsWith("}")) { 64 | return "[" + name.substring(1, name.length() - 1) + "]"; 65 | } 66 | 67 | return name; 68 | } 69 | 70 | @Override 71 | public String toString() { 72 | StringBuffer sb = new StringBuffer(); 73 | sb.append(getClass().getSimpleName()); 74 | sb.append(fixture); 75 | return sb.toString(); 76 | } 77 | 78 | @Override 79 | public boolean equals(Object o) { 80 | if (this == o) return true; 81 | if (o == null || getClass() != o.getClass()) return false; 82 | 83 | BenchmarkFixture that = (BenchmarkFixture) o; 84 | 85 | return fixture != null ? fixture.equals(that.fixture) : that.fixture == null; 86 | } 87 | 88 | @Override 89 | public int hashCode() { 90 | return fixture != null ? fixture.hashCode() : 0; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/main/java/jmh/mbr/core/model/BenchmarkMethod.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core.model; 11 | 12 | import java.lang.annotation.Annotation; 13 | import java.lang.reflect.Method; 14 | import java.lang.reflect.Parameter; 15 | import java.util.Arrays; 16 | import java.util.Objects; 17 | 18 | /** 19 | * {@link BenchmarkDescriptor} for a {@link org.openjdk.jmh.annotations.Benchmark} {@link Method}. 20 | */ 21 | public class BenchmarkMethod implements BenchmarkDescriptor, MethodAware { 22 | 23 | private final Method method; 24 | 25 | /** 26 | * Creates a new {@link BenchmarkMethod} for {@link Method}. 27 | * 28 | * @param method the underlying {@link Method}. 29 | */ 30 | public BenchmarkMethod(Method method) { 31 | 32 | Objects.requireNonNull(method, "Method must not be null!"); 33 | 34 | this.method = method; 35 | } 36 | 37 | @Override 38 | public Method getMethod() { 39 | return method; 40 | } 41 | 42 | @Override 43 | public boolean isUnderlyingMethod(Method method) { 44 | return this.method.equals(method); 45 | } 46 | 47 | /** 48 | * @return the method's name. 49 | */ 50 | public String getName() { 51 | return method.getName(); 52 | } 53 | 54 | /** 55 | * @return the method's parameters. 56 | */ 57 | public Parameter[] getParameters() { 58 | return method.getParameters(); 59 | } 60 | 61 | /** 62 | * @return the method's parameter types. 63 | */ 64 | private Class[] getParameterTypes() { 65 | return method.getParameterTypes(); 66 | } 67 | 68 | /** 69 | * @return the return type of the method. 70 | */ 71 | public Class getReturnType() { 72 | return method.getReturnType(); 73 | } 74 | 75 | /** 76 | * @return the class where the method is actually declared. 77 | */ 78 | public Class getDeclaringClass() { 79 | return method.getDeclaringClass(); 80 | } 81 | 82 | @Override 83 | public boolean equals(Object obj) { 84 | if (!BenchmarkMethod.class.isInstance(obj)) { 85 | return false; 86 | } 87 | return ((BenchmarkMethod) obj).method.equals(method); 88 | } 89 | 90 | @Override 91 | public int hashCode() { 92 | return method.hashCode(); 93 | } 94 | 95 | /** 96 | * @return the annotations on this method. 97 | */ 98 | public Annotation[] getAnnotations() { 99 | return method.getAnnotations(); 100 | } 101 | 102 | /** 103 | * Returns the annotation of type {@code annotationType} on this method, if one exists. 104 | * 105 | * @param annotationType type of annotation to retrieve. 106 | * @param annotation type. 107 | * @return the annotation or {@literal null} if not found. 108 | */ 109 | public T getAnnotation(Class annotationType) { 110 | return method.getAnnotation(annotationType); 111 | } 112 | 113 | @Override 114 | public String toString() { 115 | return method.toString(); 116 | } 117 | 118 | /** 119 | * @return {@literal true} whether the method is a parametrized one. 120 | */ 121 | public boolean isParametrized() { 122 | 123 | if (StateClass.isParametrized(method.getDeclaringClass())) { 124 | return true; 125 | } 126 | 127 | return Arrays.stream(method.getParameters()) // 128 | .map(Parameter::getType) // 129 | .anyMatch(StateClass::isParametrized); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/main/java/jmh/mbr/core/model/BenchmarkParameters.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core.model; 11 | 12 | import java.util.Collection; 13 | import java.util.LinkedHashMap; 14 | import java.util.LinkedHashSet; 15 | import java.util.List; 16 | import java.util.Map; 17 | import java.util.Set; 18 | 19 | /** 20 | * Utility class to discover {@link BenchmarkArgument} along with their parameter values from {@link StateClass state 21 | * classes}. 22 | */ 23 | class BenchmarkParameters { 24 | 25 | static Collection discover(List stateClasses) { 26 | 27 | Map argumentMap = new LinkedHashMap<>(); 28 | 29 | stateClasses.stream().map(StateClass::getParametrizedFields).flatMap(Collection::stream).forEach(it -> { 30 | 31 | List parameterValues = StateClass.getParameterValues(it); 32 | 33 | BenchmarkArgument benchmarkArgument = argumentMap.computeIfAbsent(it.getName(), BenchmarkArgument::new); 34 | benchmarkArgument.getParameters().addAll(parameterValues); 35 | }); 36 | 37 | return argumentMap.values(); 38 | } 39 | 40 | static class BenchmarkArgument { 41 | 42 | final String name; 43 | final Set parameters = new LinkedHashSet<>(); 44 | 45 | public BenchmarkArgument(String name) { 46 | this.name = name; 47 | } 48 | 49 | int getParameterCount() { 50 | return parameters.size(); 51 | } 52 | 53 | Set getParameters() { 54 | return parameters; 55 | } 56 | 57 | String getName() { 58 | return name; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/main/java/jmh/mbr/core/model/BenchmarkResults.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2020 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * https://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core.model; 11 | 12 | import java.time.Instant; 13 | import java.util.ArrayList; 14 | import java.util.Collection; 15 | import java.util.Iterator; 16 | import java.util.LinkedHashMap; 17 | import java.util.List; 18 | import java.util.Map; 19 | import java.util.Map.Entry; 20 | import java.util.function.BiFunction; 21 | import java.util.stream.Stream; 22 | 23 | import jmh.mbr.core.Environment; 24 | import jmh.mbr.core.model.BenchmarkResults.BenchmarkResult; 25 | import org.openjdk.jmh.infra.BenchmarkParams; 26 | import org.openjdk.jmh.results.Result; 27 | import org.openjdk.jmh.results.RunResult; 28 | 29 | /** 30 | * Wrapper for {@link RunResult RunResults}. 31 | */ 32 | public class BenchmarkResults implements Iterable { 33 | 34 | private final List runResults; 35 | private final MetaData metaData; 36 | 37 | public BenchmarkResults(MetaData metaData, Collection runResults) { 38 | 39 | this.runResults = new ArrayList<>(runResults); 40 | this.metaData = metaData; 41 | } 42 | 43 | /** 44 | * Obtain a {@link Stream} of {@link BenchmarkResult}. 45 | * 46 | * @return a {@link Stream} of {@link BenchmarkResult}. 47 | */ 48 | public Stream stream() { 49 | return runResults.stream().map(it -> new BenchmarkResult(metaData, it)); 50 | } 51 | 52 | public MetaData getMetaData() { 53 | return metaData; 54 | } 55 | 56 | /** 57 | * @return the raw {@link RunResult jmh results}. 58 | */ 59 | public List getRawResults() { 60 | return runResults; 61 | } 62 | 63 | @Override 64 | public Iterator iterator() { 65 | return runResults.stream().map(it -> new BenchmarkResult(metaData, it)) 66 | .iterator(); 67 | } 68 | 69 | /** 70 | * Wrapper for a single {@link RunResult} along with execution {@link MetaData}. 71 | */ 72 | public static class BenchmarkResult { 73 | 74 | private final MetaData metaData; 75 | private final RunResult runResult; 76 | 77 | public BenchmarkResult(MetaData metaData, RunResult runResult) { 78 | 79 | this.metaData = metaData; 80 | this.runResult = runResult; 81 | } 82 | 83 | public T map(BiFunction function) { 84 | return function.apply(metaData, runResult); 85 | } 86 | 87 | public MetaData getMetaData() { 88 | return metaData; 89 | } 90 | 91 | public Collection getBenchmarkResults() { 92 | return runResult.getBenchmarkResults(); 93 | } 94 | 95 | public Result getPrimaryResult() { 96 | return runResult.getPrimaryResult(); 97 | } 98 | 99 | public Map getSecondaryResults() { 100 | return runResult.getSecondaryResults(); 101 | } 102 | 103 | public org.openjdk.jmh.results.BenchmarkResult getAggregatedResult() { 104 | return runResult.getAggregatedResult(); 105 | } 106 | 107 | public BenchmarkParams getParams() { 108 | return runResult.getParams(); 109 | } 110 | } 111 | 112 | public static class MetaData { 113 | 114 | private String project; 115 | private String version; 116 | private Instant time; 117 | private String os; 118 | private Map additionalParameters = new LinkedHashMap<>(); 119 | 120 | private MetaData() { 121 | this.time = Instant.now(); 122 | } 123 | 124 | public MetaData(String project, String version) { 125 | this(); 126 | this.project = project; 127 | this.version = version; 128 | } 129 | 130 | public static MetaData none() { 131 | return new MetaData(); 132 | } 133 | 134 | public String getProject() { 135 | return project; 136 | } 137 | 138 | public String getVersion() { 139 | return version; 140 | } 141 | 142 | public Instant getTime() { 143 | return time; 144 | } 145 | 146 | public String getOs() { 147 | return os != null ? os : Environment.getOsName(); 148 | } 149 | 150 | public Map getAdditionalParameters() { 151 | return additionalParameters; 152 | } 153 | 154 | public boolean hasAdditionalMetadata() { 155 | return !additionalParameters.isEmpty(); 156 | } 157 | 158 | public static MetaData from(Map metadata) { 159 | 160 | MetaData target = new MetaData(); 161 | 162 | for (Entry entry : metadata.entrySet()) { 163 | 164 | switch (entry.getKey()) { 165 | case "os": 166 | target.os = entry.getValue().toString(); 167 | continue; 168 | case "jmh.mbr.project": 169 | target.project = entry.getValue().toString(); 170 | continue; 171 | case "jmh.mbr.project.version": 172 | target.version = entry.getValue().toString(); 173 | continue; 174 | default: 175 | target.additionalParameters.put(entry.getKey(), entry.getValue()); 176 | } 177 | } 178 | 179 | return target; 180 | } 181 | 182 | @Override 183 | public String toString() { 184 | return "MetaData{" + 185 | "project='" + project + '\'' + 186 | ", version='" + version + '\'' + 187 | ", time=" + time + 188 | ", os='" + os + '\'' + 189 | ", additionalParameters=" + additionalParameters + 190 | '}'; 191 | } 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/main/java/jmh/mbr/core/model/HierarchicalBenchmarkDescriptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core.model; 11 | 12 | import java.util.ArrayList; 13 | import java.util.Collection; 14 | import java.util.Collections; 15 | import java.util.List; 16 | import java.util.Objects; 17 | 18 | /** 19 | * {@link BenchmarkDescriptor} that represents a hierarchy of benchmark configurations. 20 | */ 21 | public class HierarchicalBenchmarkDescriptor implements BenchmarkDescriptor { 22 | 23 | private final BenchmarkDescriptor descriptor; 24 | private final List children; 25 | 26 | HierarchicalBenchmarkDescriptor(BenchmarkDescriptor descriptor, List children) { 27 | 28 | Objects.requireNonNull(descriptor, "BenchmarkDescriptor must not be null!"); 29 | Objects.requireNonNull(children, "Children must not be null!"); 30 | 31 | this.descriptor = descriptor; 32 | this.children = Collections.unmodifiableList(children); 33 | } 34 | 35 | /** 36 | * Create a {@link HierarchicalBenchmarkDescriptor} without children. 37 | * 38 | * @param descriptor the {@link BenchmarkDescriptor} that hosts benchmark. 39 | * @return the {@link HierarchicalBenchmarkDescriptor} for {@link BenchmarkDescriptor}. 40 | */ 41 | public static HierarchicalBenchmarkDescriptor create(BenchmarkDescriptor descriptor) { 42 | 43 | Objects.requireNonNull(descriptor, "BenchmarkDescriptor must not be null!"); 44 | 45 | return new HierarchicalBenchmarkDescriptor(descriptor, Collections.emptyList()); 46 | } 47 | 48 | /** 49 | * Create a {@link HierarchicalBenchmarkDescriptor} with children. 50 | * 51 | * @param descriptor the {@link BenchmarkDescriptor} that hosts benchmark. 52 | * @param children benchmark children. 53 | * @return the {@link HierarchicalBenchmarkDescriptor} for {@link BenchmarkDescriptor}. 54 | */ 55 | public static HierarchicalBenchmarkDescriptor create(BenchmarkDescriptor descriptor, 56 | Collection children) { 57 | 58 | Objects.requireNonNull(descriptor, "BenchmarkDescriptor must not be null!"); 59 | Objects.requireNonNull(children, "Children must not be null!"); 60 | 61 | return new HierarchicalBenchmarkDescriptor(descriptor, new ArrayList<>(children)); 62 | } 63 | 64 | public BenchmarkDescriptor getDescriptor() { 65 | return descriptor; 66 | } 67 | 68 | public List getChildren() { 69 | return children; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/main/java/jmh/mbr/core/model/MethodAware.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core.model; 11 | 12 | import java.lang.reflect.Method; 13 | 14 | /** 15 | * Interface exposing {@link Method} awareness of a specific descriptor object. 16 | */ 17 | public interface MethodAware { 18 | 19 | /** 20 | * @return the underlying method. 21 | */ 22 | Method getMethod(); 23 | 24 | /** 25 | * Check whether the given {@code method} is represented by this object. 26 | * 27 | * @param method must not be {@literal null}. 28 | * @return {@literal true} if the underlying {@link Method} is {@code method.} 29 | */ 30 | boolean isUnderlyingMethod(Method method); 31 | } 32 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/main/java/jmh/mbr/core/model/ParametrizedBenchmarkMethod.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core.model; 11 | 12 | import java.lang.reflect.Method; 13 | import java.util.List; 14 | 15 | /** 16 | * Represents a parametrized benchmark method along with the actual {@link BenchmarkFixture fixtures}. 17 | */ 18 | public class ParametrizedBenchmarkMethod extends HierarchicalBenchmarkDescriptor implements MethodAware { 19 | 20 | ParametrizedBenchmarkMethod(BenchmarkMethod descriptor, List children) { 21 | super(descriptor, children); 22 | } 23 | 24 | @Override 25 | public BenchmarkMethod getDescriptor() { 26 | return (BenchmarkMethod) super.getDescriptor(); 27 | } 28 | 29 | @Override 30 | public List getChildren() { 31 | return (List) super.getChildren(); 32 | } 33 | 34 | @Override 35 | public Method getMethod() { 36 | return getDescriptor().getMethod(); 37 | } 38 | 39 | @Override 40 | public boolean isUnderlyingMethod(Method method) { 41 | return getDescriptor().isUnderlyingMethod(method); 42 | } 43 | 44 | @Override 45 | public int hashCode() { 46 | return super.hashCode(); 47 | } 48 | 49 | @Override 50 | public boolean equals(Object obj) { 51 | return super.equals(obj); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/main/java/jmh/mbr/core/model/StateClass.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core.model; 11 | 12 | import java.lang.reflect.Field; 13 | import java.util.Arrays; 14 | import java.util.Collections; 15 | import java.util.List; 16 | import java.util.Objects; 17 | import java.util.stream.Collectors; 18 | import java.util.stream.Stream; 19 | 20 | import org.openjdk.jmh.annotations.Param; 21 | import org.openjdk.jmh.annotations.State; 22 | 23 | /** 24 | * Value object to encapsulate a JMH {@code @State} class. 25 | */ 26 | class StateClass { 27 | 28 | private final Class stateClass; 29 | 30 | public StateClass(Class stateClass) { 31 | this.stateClass = stateClass; 32 | } 33 | 34 | /** 35 | * Create a {@link StateClass} given {@link Class}. 36 | * 37 | * @param stateClass 38 | * @return 39 | */ 40 | public static StateClass create(Class stateClass) { 41 | 42 | Objects.requireNonNull(stateClass, "State class must not be null!"); 43 | 44 | return new StateClass(stateClass); 45 | } 46 | 47 | /** 48 | * @param stateClass 49 | * @return {@literal true} if the state class is parametrized. 50 | * @see Param 51 | */ 52 | public static boolean isParametrized(Class stateClass) { 53 | 54 | Objects.requireNonNull(stateClass, "Class must not be null!"); 55 | 56 | if (!stateClass.isAnnotationPresent(State.class)) { 57 | return false; 58 | } 59 | 60 | return Stream.concat(Arrays.stream(stateClass.getFields()), Arrays.stream(stateClass.getDeclaredFields())) 61 | .anyMatch(it -> it.isAnnotationPresent(Param.class)); 62 | } 63 | 64 | /** 65 | * @param field 66 | * @return the possible {@link Param} values for a {@link Field}. 67 | */ 68 | public static List getParameterValues(Field field) { 69 | 70 | Param annotation = field.getAnnotation(Param.class); 71 | 72 | if (annotation != null 73 | && (annotation.value().length == 0 74 | || (annotation.value().length == 1 && annotation.value()[0].equals(Param.BLANK_ARGS))) 75 | && field.getType().isEnum()) { 76 | return Arrays.asList(field.getType().getEnumConstants()).stream().map(Object::toString) 77 | .collect(Collectors.toList()); 78 | } 79 | 80 | if (annotation == null || annotation.value().length == 0 81 | || (annotation.value().length == 1 && annotation.value()[0].equals(Param.BLANK_ARGS))) { 82 | return Collections.emptyList(); 83 | } 84 | 85 | return Arrays.asList(annotation.value()); 86 | } 87 | 88 | /** 89 | * @return {@link List}of {@link Param} fields. 90 | */ 91 | public List getParametrizedFields() { 92 | 93 | return Stream.concat(Arrays.stream(stateClass.getFields()), Arrays.stream(stateClass.getDeclaredFields())) 94 | .filter(it -> it.isAnnotationPresent(Param.class)) // 95 | .distinct() // 96 | .collect(Collectors.toList()); 97 | } 98 | 99 | @Override 100 | public String toString() { 101 | StringBuffer sb = new StringBuffer(); 102 | sb.append(getClass().getSimpleName()); 103 | sb.append(" [").append(stateClass.getName()); 104 | sb.append(']'); 105 | return sb.toString(); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/test/java/jmh/mbr/core/JmhSupportUnitTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core; 11 | 12 | import static org.assertj.core.api.Assertions.*; 13 | 14 | import java.io.IOException; 15 | import java.util.Collection; 16 | import java.util.Collections; 17 | 18 | import jmh.mbr.core.model.BenchmarkResults; 19 | import jmh.mbr.core.model.BenchmarkResults.MetaData; 20 | import org.junit.jupiter.api.Test; 21 | import org.openjdk.jmh.infra.BenchmarkParams; 22 | import org.openjdk.jmh.infra.IterationParams; 23 | import org.openjdk.jmh.results.BenchmarkResult; 24 | import org.openjdk.jmh.results.IterationResult; 25 | import org.openjdk.jmh.results.RunResult; 26 | import org.openjdk.jmh.runner.format.OutputFormat; 27 | 28 | /** 29 | * Unit tests for {@link JmhSupport}. 30 | */ 31 | class JmhSupportUnitTests { 32 | 33 | @Test 34 | void shouldConsiderCompositeResultWriterUri() { 35 | 36 | TestResultsWriterFactory.REGISTRY.put("foo", FooResultWriter::new); 37 | TestResultsWriterFactory.REGISTRY.put("bar", BarResultWriter::new); 38 | 39 | System.setProperty("jmh.mbr.report.publishTo", "foo,bar,none"); 40 | 41 | try { 42 | JmhSupport support = new JmhSupport(BenchmarkConfiguration.defaultOptions()); 43 | RunResult runResult = new RunResult(null, Collections.emptyList()); 44 | support.publishResults(SilentOutputFormat.INSTANCE, new BenchmarkResults(MetaData.none(), Collections.singleton(runResult))); 45 | } finally { 46 | System.clearProperty("jmh.mbr.report.publishTo"); 47 | TestResultsWriterFactory.REGISTRY.remove("foo"); 48 | TestResultsWriterFactory.REGISTRY.remove("bar"); 49 | } 50 | 51 | assertThat(FooResultWriter.written).isTrue(); 52 | assertThat(BarResultWriter.written).isTrue(); 53 | } 54 | 55 | @Test 56 | void shouldBeAbleToWriteToEmptyUri() { 57 | 58 | TestResultsWriterFactory.REGISTRY.put("", FooResultWriter::new); 59 | 60 | try { 61 | JmhSupport support = new JmhSupport(BenchmarkConfiguration.defaultOptions()); 62 | RunResult runResult = new RunResult(null, Collections.emptyList()); 63 | support.publishResults(SilentOutputFormat.INSTANCE, new BenchmarkResults(MetaData.none(), Collections.singleton(runResult))); 64 | } finally { 65 | TestResultsWriterFactory.REGISTRY.remove(""); 66 | } 67 | 68 | assertThat(FooResultWriter.written).isTrue(); 69 | } 70 | 71 | static class FooResultWriter implements ResultsWriter { 72 | 73 | static boolean written = false; 74 | 75 | @Override 76 | public void write(OutputFormat output, BenchmarkResults results) { 77 | written = true; 78 | } 79 | } 80 | 81 | static class BarResultWriter implements ResultsWriter { 82 | 83 | static boolean written = false; 84 | 85 | @Override 86 | public void write(OutputFormat output, BenchmarkResults results) { 87 | written = true; 88 | } 89 | } 90 | 91 | enum SilentOutputFormat implements OutputFormat { 92 | 93 | INSTANCE; 94 | 95 | @Override 96 | public void iteration(BenchmarkParams benchParams, IterationParams params, int iteration) { 97 | 98 | } 99 | 100 | @Override 101 | public void iterationResult(BenchmarkParams benchParams, IterationParams params, int iteration, 102 | IterationResult data) { 103 | 104 | } 105 | 106 | @Override 107 | public void startBenchmark(BenchmarkParams benchParams) { 108 | 109 | } 110 | 111 | @Override 112 | public void endBenchmark(BenchmarkResult result) { 113 | 114 | } 115 | 116 | @Override 117 | public void startRun() { 118 | 119 | } 120 | 121 | @Override 122 | public void endRun(Collection result) { 123 | 124 | } 125 | 126 | @Override 127 | public void print(String s) { 128 | 129 | } 130 | 131 | @Override 132 | public void println(String s) { 133 | 134 | } 135 | 136 | @Override 137 | public void flush() { 138 | 139 | } 140 | 141 | @Override 142 | public void close() { 143 | 144 | } 145 | 146 | @Override 147 | public void verbosePrintln(String s) { 148 | 149 | } 150 | 151 | @Override 152 | public void write(int b) { 153 | 154 | } 155 | 156 | @Override 157 | public void write(byte[] b) throws IOException { 158 | 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/test/java/jmh/mbr/core/ResultsWriterFactoryTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core; 11 | 12 | import org.junit.jupiter.api.Test; 13 | 14 | import static org.assertj.core.api.Assertions.assertThat; 15 | 16 | class ResultsWriterFactoryTests { 17 | 18 | @Test 19 | void test() { 20 | assertThat(ResultsWriter.forUri("urn:empty")).isNotNull(); 21 | } 22 | 23 | @Test 24 | void nouri() { 25 | assertThat(ResultsWriter.forUri("")).isNull(); 26 | } 27 | 28 | @Test 29 | void empty() { 30 | assertThat(ResultsWriter.forUri("file:./target")).isNull(); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/test/java/jmh/mbr/core/TestResultsWriterFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core; 11 | 12 | import java.util.Collection; 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | import java.util.function.Supplier; 16 | 17 | import jmh.mbr.core.model.BenchmarkResults; 18 | import org.openjdk.jmh.results.RunResult; 19 | import org.openjdk.jmh.runner.format.OutputFormat; 20 | 21 | public class TestResultsWriterFactory implements ResultsWriterFactory { 22 | 23 | static Map> REGISTRY = new HashMap<>(); 24 | 25 | static { 26 | REGISTRY.put("urn:empty", TestResultsWriter::new); 27 | } 28 | 29 | @Override 30 | public ResultsWriter forUri(String uri) { 31 | return REGISTRY.getOrDefault(uri, () -> null).get(); 32 | } 33 | 34 | static class TestResultsWriter implements ResultsWriter { 35 | 36 | @Override 37 | public void write(OutputFormat output, BenchmarkResults results) { 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/test/java/jmh/mbr/core/model/BenchmarkDescriptorFactoryUnitTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.core.model; 11 | 12 | import static org.assertj.core.api.Assertions.*; 13 | 14 | import jmh.mbr.core.model.BenchmarkDescriptorFactoryUnitTests.BenchmarkClass.OneParameter; 15 | import jmh.mbr.core.model.BenchmarkDescriptorFactoryUnitTests.BenchmarkClass.Three1; 16 | import jmh.mbr.core.model.BenchmarkDescriptorFactoryUnitTests.BenchmarkClass.Three2; 17 | import jmh.mbr.core.model.BenchmarkDescriptorFactoryUnitTests.BenchmarkClass.TwoParameters; 18 | 19 | import java.util.List; 20 | 21 | import org.junit.jupiter.api.Test; 22 | import org.openjdk.jmh.annotations.Benchmark; 23 | import org.openjdk.jmh.annotations.Param; 24 | import org.openjdk.jmh.annotations.Scope; 25 | import org.openjdk.jmh.annotations.State; 26 | 27 | /** 28 | * Unit tests for {@link BenchmarkDescriptorFactory}. 29 | */ 30 | class BenchmarkDescriptorFactoryUnitTests { 31 | 32 | @Test 33 | void shouldNotCreateFixtures() { 34 | 35 | BenchmarkDescriptorFactory factory = BenchmarkDescriptorFactory.create(BenchmarkClass.class); 36 | BenchmarkMethod simple = factory.getRequiredBenchmarkMethod("simple"); 37 | 38 | List fixtures = factory.createFixtures(simple); 39 | assertThat(fixtures).isEmpty(); 40 | } 41 | 42 | @Test 43 | void shouldCreateOneFixtureForSingleParametrizedMethod() { 44 | 45 | BenchmarkDescriptorFactory factory = BenchmarkDescriptorFactory.create(BenchmarkClass.class); 46 | BenchmarkMethod single = factory.getRequiredBenchmarkMethod("single", OneParameter.class); 47 | 48 | List fixtures = factory.createFixtures(single); 49 | assertThat(fixtures).hasSize(1); 50 | } 51 | 52 | @Test 53 | void shouldCreateMultipleFixtureForParametrizedMethodWithTwoParams() { 54 | 55 | BenchmarkDescriptorFactory factory = BenchmarkDescriptorFactory.create(BenchmarkClass.class); 56 | BenchmarkMethod single = factory.getRequiredBenchmarkMethod("single", TwoParameters.class); 57 | 58 | List fixtures = factory.createFixtures(single); 59 | assertThat(fixtures).hasSize(2); 60 | } 61 | 62 | @Test 63 | void shouldCreateMultipleFixturesForParameterMatrix() { 64 | 65 | BenchmarkDescriptorFactory factory = BenchmarkDescriptorFactory.create(BenchmarkClass.class); 66 | BenchmarkMethod single = factory.getRequiredBenchmarkMethod("multi", OneParameter.class, TwoParameters.class); 67 | 68 | List fixtures = factory.createFixtures(single); 69 | assertThat(fixtures).hasSize(2); 70 | } 71 | 72 | @Test 73 | public void shouldCreateMultipleFixturesFor3x3ParameterMatrix() { 74 | 75 | BenchmarkDescriptorFactory factory = BenchmarkDescriptorFactory.create(BenchmarkClass.class); 76 | BenchmarkMethod single = factory.getRequiredBenchmarkMethod("nine", Three1.class, Three2.class); 77 | 78 | List fixtures = factory.createFixtures(single); 79 | assertThat(fixtures).hasSize(9); 80 | } 81 | 82 | @Test 83 | public void shouldCreateMultipleFixturesParametrizedBenchmarkClass() { 84 | 85 | BenchmarkDescriptorFactory factory = BenchmarkDescriptorFactory.create(ParametrizedBenchmarkClass.class); 86 | BenchmarkMethod single = factory.getRequiredBenchmarkMethod("simple"); 87 | 88 | List fixtures = factory.createFixtures(single); 89 | assertThat(fixtures).hasSize(3); 90 | } 91 | 92 | @Test 93 | public void shouldCreateMultipleFixturesEnumParametrizedBenchmarkClass() { 94 | 95 | BenchmarkDescriptorFactory factory = BenchmarkDescriptorFactory.create(EnumParametrizedBenchmarkClass.class); 96 | BenchmarkMethod single = factory.getRequiredBenchmarkMethod("simple"); 97 | 98 | List fixtures = factory.createFixtures(single); 99 | assertThat(fixtures).hasSize(3); 100 | } 101 | 102 | static class BenchmarkClass { 103 | 104 | @Benchmark 105 | void simple() { 106 | 107 | } 108 | 109 | @Benchmark 110 | void single(OneParameter single) { 111 | 112 | } 113 | 114 | @Benchmark 115 | void single(TwoParameters two) { 116 | 117 | } 118 | 119 | @Benchmark 120 | void multi(OneParameter one, TwoParameters two) { 121 | 122 | } 123 | 124 | @Benchmark 125 | void nine(Three1 one, Three2 two) { 126 | 127 | } 128 | 129 | @State(Scope.Benchmark) 130 | static class OneParameter { 131 | 132 | @Param("bar") String foo; 133 | } 134 | 135 | @State(Scope.Benchmark) 136 | static class TwoParameters { 137 | 138 | @Param({ "1", "2" }) String param2; 139 | } 140 | 141 | @State(Scope.Benchmark) 142 | static class Three1 { 143 | 144 | @Param({ "1", "2", "3" }) String foo; 145 | } 146 | 147 | @State(Scope.Benchmark) 148 | static class Three2 { 149 | 150 | @Param({ "1", "2", "3" }) String bar; 151 | } 152 | } 153 | 154 | @State(Scope.Benchmark) 155 | static class ParametrizedBenchmarkClass { 156 | 157 | @Param({ "1", "2", "3" }) String foo; 158 | 159 | @Benchmark 160 | void simple() { 161 | 162 | } 163 | } 164 | 165 | @State(Scope.Benchmark) 166 | static class EnumParametrizedBenchmarkClass { 167 | 168 | public static enum Sample { 169 | ONE, TWO, THREE 170 | } 171 | 172 | @Param Sample foo; 173 | 174 | @Benchmark 175 | void simple() { 176 | 177 | } 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /microbenchmark-runner-core/src/test/resources/META-INF/services/jmh.mbr.core.ResultsWriterFactory: -------------------------------------------------------------------------------- 1 | jmh.mbr.core.TestResultsWriterFactory 2 | -------------------------------------------------------------------------------- /microbenchmark-runner-extras/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | com.github.mp911de.microbenchmark-runner 9 | microbenchmark-runner-parent 10 | 0.6.0.BUILD-SNAPSHOT 11 | 12 | 13 | microbenchmark-runner-extras 14 | Microbenchmark Runner Extras such as CSV Results Writer 15 | 16 | 17 | 18 | 19 | org.openjdk.jmh 20 | jmh-core 21 | 22 | 23 | 24 | com.github.mp911de.microbenchmark-runner 25 | microbenchmark-runner-core 26 | ${project.version} 27 | 28 | 29 | 30 | org.elasticsearch.client 31 | elasticsearch-rest-high-level-client 32 | 7.5.0 33 | true 34 | 35 | 36 | 37 | org.junit.jupiter 38 | junit-jupiter-api 39 | test 40 | 41 | 42 | 43 | org.junit.jupiter 44 | junit-jupiter-engine 45 | test 46 | 47 | 48 | 49 | org.assertj 50 | assertj-core 51 | 52 | 53 | 54 | org.mockito 55 | mockito-junit-jupiter 56 | 3.1.0 57 | test 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /microbenchmark-runner-extras/src/main/java/jmh/mbr/extras/writer/CsvResultsFormatter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.extras.writer; 11 | 12 | import java.util.Collection; 13 | import java.util.LinkedHashMap; 14 | import java.util.Map; 15 | 16 | import org.openjdk.jmh.results.Result; 17 | import org.openjdk.jmh.results.RunResult; 18 | import org.openjdk.jmh.util.ScoreFormatter; 19 | import org.openjdk.jmh.util.Statistics; 20 | 21 | /** 22 | * Utility to create a CSV-formatted report. 23 | */ 24 | class CsvResultsFormatter { 25 | 26 | /** 27 | * Create a report in CSV format. 28 | * 29 | * @param results 30 | * @return 31 | */ 32 | static String createReport(Collection results) { 33 | 34 | StringBuilder report = new StringBuilder(System.lineSeparator()); 35 | Map params = detectParameters(results); 36 | Map auxes = detectAuxes(results); 37 | 38 | StringBuilder header = new StringBuilder(); 39 | header.append("class, method, "); 40 | params.forEach((key, value) -> header.append(key).append(", ")); 41 | auxes.forEach((key, value) -> header.append(propertyName(key)).append(", ")); 42 | header.append("median, mean, range"); 43 | report.append(header.toString()).append(System.lineSeparator()); 44 | 45 | for (RunResult result : results) { 46 | StringBuilder builder = new StringBuilder(); 47 | if (result.getParams() != null) { 48 | String benchmark = result.getParams().getBenchmark(); 49 | String cls = benchmark.contains(".") 50 | ? benchmark.substring(0, benchmark.lastIndexOf(".")) 51 | : benchmark; 52 | String mthd = benchmark.substring(benchmark.lastIndexOf(".") + 1); 53 | builder.append(cls).append(", ").append(mthd).append(", "); 54 | for (int i = 0; i < params.values().size(); i++) { 55 | boolean found = false; 56 | for (String param : result.getParams().getParamsKeys()) { 57 | if (params.get(param) == i) { 58 | builder.append(result.getParams().getParam(param)) 59 | .append(", "); 60 | found = true; 61 | } 62 | } 63 | if (!found) { 64 | builder.append(", "); 65 | } 66 | } 67 | } 68 | 69 | if (result.getAggregatedResult() != null) { 70 | 71 | Map second = result.getAggregatedResult() 72 | .getSecondaryResults(); 73 | for (int i = 0; i < auxes.values().size(); i++) { 74 | boolean found = false; 75 | for (String param : second.keySet()) { 76 | if (auxes.get(param) == i) { 77 | builder.append(ScoreFormatter.format( 78 | second.get(param).getStatistics().getPercentile(0.5))) 79 | .append(", "); 80 | found = true; 81 | } 82 | } 83 | if (!found) { 84 | builder.append(", "); 85 | } 86 | } 87 | // primary result is derived from aggregate result 88 | Statistics statistics = result.getPrimaryResult().getStatistics(); 89 | builder.append(ScoreFormatter.format(statistics.getPercentile(0.5))); 90 | builder.append(", "); 91 | builder.append(ScoreFormatter.format(statistics.getMean())); 92 | builder.append(", "); 93 | double error = (statistics.getMax() - statistics.getMin()) / 2; 94 | builder.append(ScoreFormatter.format(error)); 95 | 96 | report.append(builder.toString()).append(System.lineSeparator()); 97 | } 98 | } 99 | 100 | return report.toString(); 101 | } 102 | 103 | private static Map detectAuxes(Collection results) { 104 | Map auxes = new LinkedHashMap<>(); 105 | int auxPlaces = 0; 106 | for (RunResult result : results) { 107 | if (result.getAggregatedResult() != null) { 108 | @SuppressWarnings("rawtypes") 109 | Map second = result.getAggregatedResult() 110 | .getSecondaryResults(); 111 | if (second != null) { 112 | for (String aux : second.keySet()) { 113 | int count = auxPlaces; 114 | auxes.computeIfAbsent(aux, key -> count); 115 | auxPlaces++; 116 | } 117 | } 118 | } 119 | } 120 | return auxes; 121 | } 122 | 123 | private static Map detectParameters(Collection results) { 124 | Map params = new LinkedHashMap<>(); 125 | int paramPlaces = 0; 126 | for (RunResult result : results) { 127 | if (result.getParams() != null) { 128 | for (String param : result.getParams().getParamsKeys()) { 129 | int count = paramPlaces; 130 | if (params.containsKey(param)) { 131 | continue; 132 | } 133 | params.put(param, count); 134 | paramPlaces++; 135 | } 136 | } 137 | } 138 | return params; 139 | } 140 | 141 | private static String propertyName(String key) { 142 | if (key.matches("get[A-Z].*")) { 143 | key = changeFirstCharacterCase(key.substring(3), false); 144 | } 145 | return key; 146 | } 147 | 148 | private static String changeFirstCharacterCase(String str, boolean capitalize) { 149 | if (str == null || str.length() == 0) { 150 | return str; 151 | } 152 | 153 | char baseChar = str.charAt(0); 154 | char updatedChar; 155 | if (capitalize) { 156 | updatedChar = Character.toUpperCase(baseChar); 157 | } 158 | else { 159 | updatedChar = Character.toLowerCase(baseChar); 160 | } 161 | if (baseChar == updatedChar) { 162 | return str; 163 | } 164 | 165 | char[] chars = str.toCharArray(); 166 | chars[0] = updatedChar; 167 | return new String(chars, 0, chars.length); 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /microbenchmark-runner-extras/src/main/java/jmh/mbr/extras/writer/CsvResultsWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2020 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.extras.writer; 11 | 12 | import java.io.File; 13 | import java.io.FileNotFoundException; 14 | import java.io.IOException; 15 | import java.util.Collections; 16 | 17 | import jmh.mbr.core.ResultsWriter; 18 | import jmh.mbr.core.model.BenchmarkResults; 19 | import org.openjdk.jmh.runner.format.OutputFormat; 20 | import org.openjdk.jmh.util.FileUtils; 21 | 22 | class CsvResultsWriter implements ResultsWriter { 23 | 24 | private final String uri; 25 | 26 | public CsvResultsWriter(String uri) { 27 | this.uri = uri; 28 | } 29 | 30 | @Override 31 | public void write(OutputFormat output, BenchmarkResults results) { 32 | 33 | String report; 34 | 35 | try { 36 | report = CsvResultsFormatter.createReport(results.getRawResults()); 37 | } 38 | catch (Exception e) { 39 | output.println("Report creation failed: " + StackTraceCapture.from(e)); 40 | return; 41 | } 42 | try { 43 | 44 | File file = new File(uri.substring("csv:".length())).getCanonicalFile(); 45 | output.println(System.lineSeparator()); 46 | output.println("Writing result to file: " + file); 47 | 48 | File parent = file.getParentFile(); 49 | if (parent != null) { 50 | 51 | parent.mkdirs(); 52 | 53 | if (parent.exists()) { 54 | FileUtils.writeLines(file, Collections.singleton(report)); 55 | return; 56 | } 57 | } 58 | 59 | throw new FileNotFoundException("Parent directory " + parent + " does not exist"); 60 | } 61 | catch (IOException e) { 62 | output.println("Write failed: " + e 63 | .getMessage() + " " + StackTraceCapture.from(e)); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /microbenchmark-runner-extras/src/main/java/jmh/mbr/extras/writer/CsvResultsWriterFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.extras.writer; 11 | 12 | import jmh.mbr.core.ResultsWriter; 13 | import jmh.mbr.core.ResultsWriterFactory; 14 | 15 | /** 16 | * A {@link ResultsWriterFactory} that writes the output in csv format (to the console and to a file). Activated with 17 | * -Djmh.mbr.report.publishTo=csv:./path/to/file.csv. The file will be overwritten if it already exists. If the file 18 | * cannot be written a warning will be printed on the console. 19 | */ 20 | public class CsvResultsWriterFactory implements ResultsWriterFactory { 21 | 22 | @Override 23 | public ResultsWriter forUri(String uri) { 24 | 25 | if (!uri.startsWith("csv:")) { 26 | return null; 27 | } 28 | 29 | return new CsvResultsWriter(uri); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /microbenchmark-runner-extras/src/main/java/jmh/mbr/extras/writer/ElasticsearchResultsWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2020 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * https://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.extras.writer; 11 | 12 | import java.io.IOException; 13 | import java.util.Base64; 14 | 15 | import jmh.mbr.core.ResultsWriter; 16 | import jmh.mbr.core.model.BenchmarkResults; 17 | import jmh.mbr.core.model.BenchmarkResults.BenchmarkResult; 18 | import org.apache.http.Header; 19 | import org.apache.http.HttpHeaders; 20 | import org.apache.http.HttpHost; 21 | import org.apache.http.message.BasicHeader; 22 | import org.elasticsearch.action.index.IndexRequest; 23 | import org.elasticsearch.client.RequestOptions; 24 | import org.elasticsearch.client.RestClient; 25 | import org.elasticsearch.client.RestClientBuilder; 26 | import org.elasticsearch.client.RestHighLevelClient; 27 | import org.elasticsearch.common.xcontent.XContentType; 28 | import org.openjdk.jmh.runner.format.OutputFormat; 29 | 30 | /** 31 | * {@link ResultsWriter} to write {@link BenchmarkResults} to Elasticserarch. 32 | */ 33 | public class ElasticsearchResultsWriter implements ResultsWriter { 34 | 35 | private final RestHighLevelClient client; 36 | 37 | public ElasticsearchResultsWriter(String uri) { 38 | this(createClient(ConnectionString.fromUri(uri))); 39 | } 40 | 41 | ElasticsearchResultsWriter(RestHighLevelClient client) { 42 | this.client = client; 43 | } 44 | 45 | @Override 46 | public void write(OutputFormat output, BenchmarkResults results) { 47 | results.forEach(result -> formatAndPublish(output, result)); 48 | } 49 | 50 | private void formatAndPublish(OutputFormat output, BenchmarkResult result) { 51 | publishJson(output, result.getMetaData().getProject(), result 52 | .map(JsonResultsFormatter::format)); 53 | } 54 | 55 | void publishJson(OutputFormat output, String index, String json) { 56 | 57 | IndexRequest request = new IndexRequest(index); 58 | request.source(json, XContentType.JSON); 59 | 60 | try { 61 | client.index(request, RequestOptions.DEFAULT); 62 | } 63 | catch (IOException e) { 64 | output.println("Write failed: " + e 65 | .getMessage() + " " + StackTraceCapture.from(e)); 66 | } 67 | } 68 | 69 | static RestHighLevelClient createClient(ConnectionString connectionString) { 70 | 71 | RestClientBuilder builder = RestClient.builder(connectionString.getHttpHost()); 72 | 73 | if (connectionString.hasCredentials()) { 74 | builder.setDefaultHeaders(new Header[] { 75 | new BasicHeader(HttpHeaders.AUTHORIZATION, connectionString 76 | .getBasicAuth()) 77 | }); 78 | } 79 | 80 | return new RestHighLevelClient(builder); 81 | } 82 | 83 | /** 84 | * elasticsearch://[username]:[password]@[host]:[port]/ 85 | */ 86 | static class ConnectionString { 87 | 88 | final String host; 89 | final int port; 90 | final String username; 91 | final char[] password; 92 | final boolean ssl; 93 | 94 | ConnectionString(String host, int port, String username, char[] password, boolean ssl) { 95 | 96 | this.host = host; 97 | this.port = port; 98 | this.username = username; 99 | this.password = password; 100 | this.ssl = ssl; 101 | } 102 | 103 | static ConnectionString fromUri(String uri) { 104 | 105 | boolean ssl = isSsl(uri); 106 | 107 | if (!uri.contains("://")) { 108 | return new ConnectionString("localhost", 9200, null, null, ssl); 109 | } 110 | 111 | String authority = uri.substring(uri.indexOf("://") + 3); 112 | 113 | UserPassword upw = UserPassword.from(authority); 114 | HostPort hostPort = HostPort.from(authority); 115 | 116 | return new ConnectionString(hostPort.host, hostPort.port, upw.username, upw.password, ssl); 117 | } 118 | 119 | HttpHost getHttpHost() { 120 | return new HttpHost(this.host, this.port, this.ssl ? "https" : "http"); 121 | } 122 | 123 | boolean hasCredentials() { 124 | return this.username != null && this.password != null; 125 | } 126 | 127 | private String getBasicAuth() { 128 | 129 | String credentialsString = this.username + ":" + new String(this.password); 130 | byte[] encodedBytes = Base64.getEncoder() 131 | .encode(credentialsString.getBytes()); 132 | return "Basic " + new String(encodedBytes); 133 | } 134 | 135 | private static boolean isSsl(String uri) { 136 | return uri.startsWith("elasticsearchs"); 137 | } 138 | 139 | private static class UserPassword { 140 | 141 | final String username; 142 | final char[] password; 143 | 144 | public UserPassword(String username, char[] password) { 145 | this.username = username; 146 | this.password = password; 147 | } 148 | 149 | static UserPassword none() { 150 | return new UserPassword(null, null); 151 | } 152 | 153 | static UserPassword from(String connectionString) { 154 | 155 | if (!connectionString.contains("@")) { 156 | return none(); 157 | } 158 | 159 | String[] args = connectionString.split("@"); 160 | 161 | if (!args[0].contains(":")) { 162 | return none(); 163 | } 164 | 165 | String[] userPwd = args[0].split(":"); 166 | return new UserPassword(userPwd[0], userPwd[1].toCharArray()); 167 | } 168 | } 169 | 170 | private static class HostPort { 171 | 172 | final String host; 173 | final int port; 174 | 175 | public HostPort(String host, int port) { 176 | this.host = host; 177 | this.port = port; 178 | } 179 | 180 | static HostPort local() { 181 | return new HostPort("localhost", 9200); 182 | } 183 | 184 | static HostPort from(String connectionString) { 185 | 186 | String part = connectionString; 187 | 188 | if (connectionString.contains("@")) { 189 | String[] args = connectionString.split("@"); 190 | part = args[1]; 191 | } 192 | 193 | if (!part.contains(":")) { 194 | return local(); 195 | } 196 | 197 | String[] hostPort = part.split(":"); 198 | return new HostPort(hostPort[0], Integer.parseInt(hostPort[1])); 199 | } 200 | } 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /microbenchmark-runner-extras/src/main/java/jmh/mbr/extras/writer/ElasticserachResultsWriterFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2020 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * https://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.extras.writer; 11 | 12 | import jmh.mbr.core.ResultsWriter; 13 | import jmh.mbr.core.ResultsWriterFactory; 14 | 15 | /** 16 | * {@link ResultsWriterFactory} for Elasticsearch. 17 | * Activated with -Djmh.mbr.report.publishTo=elasticsearch://[username]:[password]@[host]:[port]/. The index is derived from the project name ({@code jmh.mbr.project}). 18 | * 19 | * @see ElasticsearchResultsWriter 20 | */ 21 | public class ElasticserachResultsWriterFactory implements ResultsWriterFactory { 22 | 23 | @Override 24 | public ResultsWriter forUri(String uri) { 25 | 26 | if (uri == null || !uri.startsWith("elasticsearch")) { 27 | return null; 28 | } 29 | 30 | return new ElasticsearchResultsWriter(uri); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /microbenchmark-runner-extras/src/main/java/jmh/mbr/extras/writer/StackTraceCapture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.extras.writer; 11 | 12 | import java.io.PrintWriter; 13 | import java.io.StringWriter; 14 | 15 | /** 16 | * Utility to capture a {@link Throwable#getStackTrace() stack trace} to {@link String}. 17 | */ 18 | class StackTraceCapture { 19 | 20 | static String from(Throwable throwable) { 21 | StringWriter trace = new StringWriter(); 22 | throwable.printStackTrace(new PrintWriter(trace)); 23 | return trace.toString(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /microbenchmark-runner-extras/src/main/java/jmh/mbr/extras/writer/SysoutCsvResultsWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2020 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.extras.writer; 11 | 12 | import jmh.mbr.core.ResultsWriter; 13 | import jmh.mbr.core.model.BenchmarkResults; 14 | import org.openjdk.jmh.runner.format.OutputFormat; 15 | 16 | class SysoutCsvResultsWriter implements ResultsWriter { 17 | 18 | private final String uri; 19 | 20 | SysoutCsvResultsWriter(String uri) { 21 | this.uri = uri; 22 | } 23 | 24 | @Override 25 | public void write(OutputFormat output, BenchmarkResults results) { 26 | 27 | try { 28 | 29 | String report = CsvResultsFormatter.createReport(results.getRawResults()); 30 | output.println(report); 31 | } catch (Exception e) { 32 | output.println("Report creation failed: " + StackTraceCapture.from(e)); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /microbenchmark-runner-extras/src/main/java/jmh/mbr/extras/writer/SysoutCsvResultsWriterFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.extras.writer; 11 | 12 | import jmh.mbr.core.ResultsWriter; 13 | import jmh.mbr.core.ResultsWriterFactory; 14 | 15 | /** 16 | * A {@link ResultsWriterFactory} that writes the output in csv format (to the console). Activated with 17 | * -Djmh.mbr.report.publishTo=sysout. 18 | */ 19 | public class SysoutCsvResultsWriterFactory implements ResultsWriterFactory { 20 | 21 | @Override 22 | public ResultsWriter forUri(String uri) { 23 | 24 | if (uri == null || uri.trim().isEmpty() || uri.equals("sysout")) { 25 | return new SysoutCsvResultsWriter(uri); 26 | } 27 | 28 | return null; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /microbenchmark-runner-extras/src/main/resources/META-INF/services/jmh.mbr.core.ResultsWriterFactory: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019-2020 the original author or authors. 3 | # 4 | # All rights reserved. This program and the accompanying materials are 5 | # made available under the terms of the Eclipse Public License v2.0 which 6 | # accompanies this distribution and is available at 7 | # 8 | # http://www.eclipse.org/legal/epl-v20.html 9 | # 10 | jmh.mbr.extras.writer.CsvResultsWriterFactory 11 | jmh.mbr.extras.writer.SysoutCsvResultsWriterFactory 12 | jmh.mbr.extras.writer.ElasticserachResultsWriterFactory 13 | -------------------------------------------------------------------------------- /microbenchmark-runner-extras/src/test/java/jmh/mbr/extras/RunResultGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * https://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.extras; 11 | 12 | import java.util.ArrayList; 13 | import java.util.Collection; 14 | import java.util.Collections; 15 | import java.util.Random; 16 | import java.util.TreeSet; 17 | import java.util.concurrent.TimeUnit; 18 | 19 | import org.openjdk.jmh.annotations.Mode; 20 | import org.openjdk.jmh.infra.BenchmarkParams; 21 | import org.openjdk.jmh.infra.IterationParams; 22 | import org.openjdk.jmh.results.BenchmarkResult; 23 | import org.openjdk.jmh.results.IterationResult; 24 | import org.openjdk.jmh.results.ResultRole; 25 | import org.openjdk.jmh.results.RunResult; 26 | import org.openjdk.jmh.results.ThroughputResult; 27 | import org.openjdk.jmh.runner.IterationType; 28 | import org.openjdk.jmh.runner.WorkloadParams; 29 | import org.openjdk.jmh.runner.options.TimeValue; 30 | 31 | 32 | public class RunResultGenerator { 33 | 34 | private static final String JVM_DUMMY = "javadummy"; 35 | 36 | private static final String JDK_VERSION_DUMMY = "jdk-11.0.1.jdk"; 37 | 38 | private static final String VM_NAME_DUMMY = "DummyVM"; 39 | 40 | private static final String VM_VERSION_DUMMY = "4711"; 41 | 42 | private static final String JMH_VERSION_DUMMY = "11.0.1+13-LTS"; 43 | 44 | public static Collection generate(String name) { 45 | 46 | BenchmarkParams params = params(name); 47 | return generate(params, benchmarkResults(params, 3, 10, 20, 30)); 48 | } 49 | 50 | public static Collection generate(BenchmarkParams params, Collection results) { 51 | return Collections.singleton(new RunResult(params, results)); 52 | } 53 | 54 | 55 | public static BenchmarkParams params(String name) { 56 | 57 | BenchmarkParams params = new BenchmarkParams( 58 | name+".log", 59 | name + ".benchmark_" + Mode.Throughput, 60 | false, 61 | 1, 62 | new int[]{1}, 63 | Collections.emptyList(), 64 | 65 | 1, 66 | 1, 67 | new IterationParams(IterationType.WARMUP, 10, TimeValue.seconds(5), 1), 68 | new IterationParams(IterationType.MEASUREMENT, 10, TimeValue.seconds(10), 1), 69 | Mode.Throughput, 70 | new WorkloadParams(), 71 | TimeUnit.SECONDS, 1, 72 | JVM_DUMMY, 73 | Collections.emptyList(), 74 | JDK_VERSION_DUMMY, VM_NAME_DUMMY, VM_VERSION_DUMMY, JMH_VERSION_DUMMY, 75 | TimeValue.days(1)); 76 | 77 | return params; 78 | } 79 | 80 | public static Collection benchmarkResults(BenchmarkParams params, int iterations, Integer... ops) { 81 | 82 | Collection benchmarkResults = new ArrayList<>(); 83 | Collection iterationResults = new ArrayList<>(iterations); 84 | 85 | for (int iteration = 0; iteration < iterations; iteration++) { 86 | IterationResult iterationResult = generateIterationResult(iteration, params, ops); 87 | iterationResults.add(iterationResult); 88 | } 89 | 90 | benchmarkResults.add(new BenchmarkResult(params, iterationResults)); 91 | return benchmarkResults; 92 | } 93 | 94 | private static IterationResult generateIterationResult(int iteration, BenchmarkParams params, Integer[] ops) { 95 | 96 | IterationResult iterationResult = new IterationResult(params, params.getMeasurement(), null); 97 | for (Integer operations : ops) { 98 | iterationResult.addResult(new ThroughputResult(ResultRole.PRIMARY, params.getBenchmark()+".log", operations, 1000 * 1000, TimeUnit.MILLISECONDS)); 99 | } 100 | return iterationResult; 101 | } 102 | 103 | 104 | public static Collection random() { 105 | 106 | Collection results = new TreeSet<>(RunResult.DEFAULT_SORT_COMPARATOR); 107 | 108 | Random r = new Random(12345); 109 | Random ar = new Random(12345); 110 | 111 | for (int b = 0; b < r.nextInt(10); b++) { 112 | 113 | WorkloadParams ps = new WorkloadParams(); 114 | ps.put("param0", "value0", 0); 115 | ps.put("param1", "[value1]", 1); 116 | ps.put("param2", "{value2}", 2); 117 | ps.put("param3", "'value3'", 3); 118 | ps.put("param4", "\"value4\"", 4); 119 | BenchmarkParams params = new BenchmarkParams( 120 | "benchmark_" + b, 121 | RunResultGenerator.class.getName() + ".benchmark_" + b + "_" + Mode.Throughput, 122 | false, 123 | r.nextInt(1000), 124 | new int[]{r.nextInt(1000)}, 125 | Collections.emptyList(), 126 | 127 | r.nextInt(1000), 128 | r.nextInt(1000), 129 | new IterationParams(IterationType.WARMUP, r.nextInt(1000), TimeValue.seconds(r.nextInt(1000)), 1), 130 | new IterationParams(IterationType.MEASUREMENT, r.nextInt(1000), TimeValue.seconds(r.nextInt(1000)), 1), 131 | Mode.Throughput, 132 | ps, 133 | TimeUnit.SECONDS, 1, 134 | JVM_DUMMY, 135 | Collections.emptyList(), 136 | JDK_VERSION_DUMMY, VM_NAME_DUMMY, VM_VERSION_DUMMY, JMH_VERSION_DUMMY, 137 | TimeValue.days(1)); 138 | 139 | Collection benchmarkResults = new ArrayList<>(); 140 | for (int f = 0; f < r.nextInt(10); f++) { 141 | Collection iterResults = new ArrayList<>(); 142 | for (int c = 0; c < r.nextInt(10); c++) { 143 | IterationResult res = new IterationResult(params, params.getMeasurement(), null); 144 | res.addResult(new ThroughputResult(ResultRole.PRIMARY, "test", r.nextInt(1000), 1000 * 1000, TimeUnit.MILLISECONDS)); 145 | res.addResult(new ThroughputResult(ResultRole.SECONDARY, "secondary1", r.nextInt(1000), 1000 * 1000, TimeUnit.MILLISECONDS)); 146 | res.addResult(new ThroughputResult(ResultRole.SECONDARY, "secondary2", r.nextInt(1000), 1000 * 1000, TimeUnit.MILLISECONDS)); 147 | if (ar.nextBoolean()) { 148 | res.addResult(new ThroughputResult(ResultRole.SECONDARY, "secondary3", ar.nextInt(1000), 1000 * 1000, TimeUnit.MILLISECONDS)); 149 | } 150 | iterResults.add(res); 151 | } 152 | benchmarkResults.add(new BenchmarkResult(params, iterResults)); 153 | } 154 | results.add(new RunResult(params, benchmarkResults)); 155 | } 156 | return results; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /microbenchmark-runner-extras/src/test/java/jmh/mbr/extras/writer/CsvResultsWriterFactoryTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.extras.writer; 11 | 12 | import java.io.ByteArrayOutputStream; 13 | import java.io.File; 14 | import java.io.OutputStream; 15 | import java.io.PrintStream; 16 | import java.util.Arrays; 17 | import java.util.Collections; 18 | 19 | import jmh.mbr.core.model.BenchmarkResults; 20 | import jmh.mbr.core.model.BenchmarkResults.MetaData; 21 | import org.junit.jupiter.api.BeforeEach; 22 | import org.junit.jupiter.api.Test; 23 | import org.openjdk.jmh.results.RunResult; 24 | import org.openjdk.jmh.runner.format.OutputFormat; 25 | import org.openjdk.jmh.runner.format.OutputFormatFactory; 26 | import org.openjdk.jmh.runner.options.VerboseMode; 27 | 28 | import static org.assertj.core.api.Assertions.*; 29 | 30 | class CsvResultsWriterFactoryTests { 31 | 32 | private static String TARGET_FILE = "target/result.csv"; 33 | 34 | private CsvResultsWriterFactory factory = new CsvResultsWriterFactory(); 35 | 36 | @BeforeEach 37 | void init() { 38 | File target = new File(TARGET_FILE); 39 | if (target.exists()) { 40 | assertThat(target.delete()).isTrue(); 41 | } 42 | } 43 | 44 | @Test 45 | void validUri() { 46 | assertThat(factory.forUri("csv:target/empty.csv")).isNotNull(); 47 | } 48 | 49 | @Test 50 | void writeEmptyResults() { 51 | RunResult runResult = new RunResult(null, Collections.emptyList()); 52 | output(runResult); 53 | assertThat(new File(TARGET_FILE)).exists(); 54 | } 55 | 56 | private String output(RunResult... runResult) { 57 | OutputStream stream = new ByteArrayOutputStream(); 58 | OutputFormat output = OutputFormatFactory 59 | .createFormatInstance(new PrintStream(stream), VerboseMode.NORMAL); 60 | factory.forUri("csv:" + TARGET_FILE).write(output, new BenchmarkResults(MetaData.none(), Arrays.asList(runResult))); 61 | return stream.toString(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /microbenchmark-runner-extras/src/test/java/jmh/mbr/extras/writer/ElasticsearchResultsWriterFactoryTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * https://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.extras.writer; 11 | 12 | import static org.assertj.core.api.Assertions.*; 13 | 14 | import org.junit.jupiter.api.Test; 15 | 16 | class ElasticsearchResultsWriterFactoryTests { 17 | 18 | private ElasticserachResultsWriterFactory factory = new ElasticserachResultsWriterFactory(); 19 | 20 | @Test 21 | void nullUri() { 22 | assertThat(factory.forUri(null)).isNull(); 23 | } 24 | 25 | @Test 26 | void emptyUri() { 27 | assertThat(factory.forUri("")).isNull(); 28 | } 29 | 30 | @Test 31 | void elasticsearchEnablesFactory() { 32 | assertThat(factory.forUri("elasticsearch")).isNotNull(); 33 | } 34 | 35 | @Test 36 | void elasticsearchWithSslEnablesFactory() { 37 | assertThat(factory.forUri("elasticsearchs")).isNotNull(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /microbenchmark-runner-extras/src/test/java/jmh/mbr/extras/writer/ElasticsearchResultsWriterUnitTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * https://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.extras.writer; 11 | 12 | import static org.assertj.core.api.Assertions.*; 13 | 14 | import jmh.mbr.extras.writer.ElasticsearchResultsWriter.ConnectionString; 15 | import org.junit.jupiter.api.Test; 16 | 17 | class ElasticsearchResultsWriterUnitTests { 18 | 19 | // todo: test all the escaping paths for usernames containing : and @ but that is furture work 20 | 21 | @Test 22 | void justHostAndPort() { 23 | 24 | ConnectionString connectionString = ElasticsearchResultsWriter.ConnectionString.fromUri("elasticsearch://es-server:666"); 25 | assertThat(connectionString.host).isEqualTo("es-server"); 26 | assertThat(connectionString.port).isEqualTo(666); 27 | assertThat(connectionString.password).isNull(); 28 | assertThat(connectionString.username).isNull(); 29 | assertThat(connectionString.ssl).isFalse(); 30 | } 31 | 32 | @Test 33 | void justServicename() { 34 | 35 | ConnectionString connectionString = ElasticsearchResultsWriter.ConnectionString.fromUri("elasticsearch"); 36 | assertThat(connectionString.host).isEqualTo("localhost"); 37 | assertThat(connectionString.port).isEqualTo(9200); 38 | assertThat(connectionString.password).isNull(); 39 | assertThat(connectionString.username).isNull(); 40 | assertThat(connectionString.ssl).isFalse(); 41 | } 42 | 43 | @Test 44 | void withSSL() { 45 | 46 | ConnectionString connectionString = ElasticsearchResultsWriter.ConnectionString.fromUri("elasticsearchs://es-server:666"); 47 | assertThat(connectionString.host).isEqualTo("es-server"); 48 | assertThat(connectionString.port).isEqualTo(666); 49 | assertThat(connectionString.password).isNull(); 50 | assertThat(connectionString.username).isNull(); 51 | assertThat(connectionString.ssl).isTrue(); 52 | } 53 | 54 | @Test 55 | void withUserPassword() { 56 | 57 | ConnectionString connectionString = ElasticsearchResultsWriter.ConnectionString.fromUri("elasticsearch://es-user:es-pwd@es-host:666"); 58 | assertThat(connectionString.host).isEqualTo("es-host"); 59 | assertThat(connectionString.port).isEqualTo(666); 60 | assertThat(connectionString.password).isEqualTo("es-pwd".toCharArray()); 61 | assertThat(connectionString.username).isEqualTo("es-user"); 62 | assertThat(connectionString.ssl).isFalse(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /microbenchmark-runner-extras/src/test/java/jmh/mbr/extras/writer/JsonResultsFormatterUnitTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * https://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.extras.writer; 11 | 12 | import static org.openjdk.jmh.results.format.ResultFormatType.*; 13 | 14 | import java.io.ByteArrayOutputStream; 15 | import java.io.PrintStream; 16 | import java.io.UnsupportedEncodingException; 17 | import java.nio.charset.StandardCharsets; 18 | import java.util.LinkedHashMap; 19 | import java.util.List; 20 | import java.util.Map; 21 | 22 | import jmh.mbr.core.model.BenchmarkResults; 23 | import jmh.mbr.core.model.BenchmarkResults.MetaData; 24 | import jmh.mbr.extras.RunResultGenerator; 25 | import org.assertj.core.api.Assertions; 26 | import org.junit.jupiter.api.Disabled; 27 | import org.junit.jupiter.api.Test; 28 | import org.openjdk.jmh.results.format.ResultFormatFactory; 29 | import org.openjdk.jmh.results.format.ResultFormatType; 30 | 31 | class JsonResultsFormatterUnitTests { 32 | 33 | @Test 34 | @Disabled 35 | void nativeJson() throws UnsupportedEncodingException { 36 | 37 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 38 | ResultFormatFactory.getInstance(ResultFormatType.JSON, new PrintStream(baos, true, "UTF-8")).writeOut(RunResultGenerator.random()); 39 | 40 | String results = new String(baos.toByteArray(), StandardCharsets.UTF_8); 41 | System.out.println("results: " + results); 42 | } 43 | 44 | @Test 45 | @Disabled 46 | void nativeText() throws UnsupportedEncodingException { 47 | 48 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 49 | ResultFormatFactory.getInstance(TEXT, new PrintStream(baos, true, "UTF-8")).writeOut(RunResultGenerator.random()); 50 | 51 | String results = new String(baos.toByteArray(), StandardCharsets.UTF_8); 52 | System.out.println("results: " + results); 53 | } 54 | 55 | @Test 56 | void json() { 57 | 58 | MetaData metaData = new MetaData("test-project", "1.0.0.SNAPSHOT"); 59 | BenchmarkResults results = new BenchmarkResults(metaData, RunResultGenerator.generate("UnitTest")); 60 | 61 | List json = JsonResultsFormatter.createReport(results); 62 | 63 | json.forEach(result -> { 64 | 65 | Assertions.assertThat(result) 66 | .contains("\"project\" : \"test-project\"") 67 | .contains("\"group\" : \"UnitTest\"") 68 | .contains("\"benchmark\" : \"log\""); 69 | }); 70 | } 71 | 72 | @Test 73 | void metadata() { 74 | 75 | Map raw = new LinkedHashMap<>(); 76 | raw.put("jmh.mbr.project", "test-project"); 77 | raw.put("jmh.mbr.project.version", "1.0.0.SNAPSHOT"); 78 | raw.put("jmh.mbr.marker-1", "1-marker"); 79 | raw.put("jmh.mbr.marker-2", "2-marker"); 80 | 81 | MetaData metaData = MetaData.from(raw); 82 | BenchmarkResults results = new BenchmarkResults(metaData, RunResultGenerator.generate("UnitTest")); 83 | 84 | List json = JsonResultsFormatter.createReport(results); 85 | 86 | json.forEach(result -> { 87 | 88 | Assertions.assertThat(result) 89 | .contains(" \"jmh.mbr.marker-1\" : \"1-marker\",") 90 | .contains("\"jmh.mbr.marker-2\" : \"2-marker\""); 91 | }); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /microbenchmark-runner-extras/src/test/java/jmh/mbr/extras/writer/SysoutResultsWriterFactoryTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.extras.writer; 11 | 12 | import static org.assertj.core.api.Assertions.*; 13 | 14 | import java.io.ByteArrayOutputStream; 15 | import java.io.OutputStream; 16 | import java.io.PrintStream; 17 | import java.util.Arrays; 18 | import java.util.Collection; 19 | import java.util.Collections; 20 | import java.util.concurrent.TimeUnit; 21 | 22 | import jmh.mbr.core.ResultsWriter; 23 | import jmh.mbr.core.model.BenchmarkResults; 24 | import jmh.mbr.core.model.BenchmarkResults.MetaData; 25 | import org.junit.jupiter.api.Test; 26 | import org.openjdk.jmh.annotations.Mode; 27 | import org.openjdk.jmh.infra.BenchmarkParams; 28 | import org.openjdk.jmh.results.AverageTimeResult; 29 | import org.openjdk.jmh.results.BenchmarkResult; 30 | import org.openjdk.jmh.results.IterationResult; 31 | import org.openjdk.jmh.results.ResultRole; 32 | import org.openjdk.jmh.results.RunResult; 33 | import org.openjdk.jmh.runner.WorkloadParams; 34 | import org.openjdk.jmh.runner.format.OutputFormat; 35 | import org.openjdk.jmh.runner.format.OutputFormatFactory; 36 | import org.openjdk.jmh.runner.options.TimeValue; 37 | import org.openjdk.jmh.runner.options.VerboseMode; 38 | import org.openjdk.jmh.util.ScoreFormatter; 39 | 40 | class SysoutResultsWriterFactoryTests { 41 | 42 | private SysoutCsvResultsWriterFactory factory = new SysoutCsvResultsWriterFactory(); 43 | 44 | @Test 45 | void emptyUri() { 46 | ResultsWriter writer = factory.forUri(null); 47 | assertThat(writer).isNotNull(); 48 | } 49 | 50 | @Test 51 | void sysoutEnablesStdOut() { 52 | ResultsWriter writer = factory.forUri("sysout"); 53 | assertThat(writer).isNotNull(); 54 | } 55 | 56 | @Test 57 | void noneDisablesStdOut() { 58 | ResultsWriter writer = factory.forUri("none"); 59 | assertThat(writer).isNull(); 60 | } 61 | 62 | @Test 63 | void writeActualResults() { 64 | BenchmarkParams params = params(); 65 | Collection data = Collections 66 | .singletonList(new BenchmarkResult(null, data())); 67 | RunResult runResult = new RunResult(params, data); 68 | String result = output(runResult); 69 | assertThat(result) 70 | .containsSubsequence("class, method, median, mean, range", "Foo, exec"); 71 | } 72 | 73 | @Test 74 | void writeParamResult() { 75 | BenchmarkParams params = params("a=b"); 76 | Collection data = Collections 77 | .singletonList(new BenchmarkResult(null, data())); 78 | RunResult runResult = new RunResult(params, data); 79 | String result = output(runResult); 80 | assertThat(result) 81 | .containsSubsequence("class, method, a, median, mean, range", "Foo, exec, b"); 82 | } 83 | 84 | @Test 85 | void writeSecondaryResult() { 86 | BenchmarkParams params = params("a=b"); 87 | Collection data = Collections 88 | .singletonList(new BenchmarkResult(null, data("bar"))); 89 | RunResult runResult = new RunResult(params, data); 90 | String result = output(runResult); 91 | assertThat(result) 92 | .containsSubsequence("class, method, a, bar, median, mean, range", "Foo, exec, b"); 93 | } 94 | 95 | @Test 96 | void writeMixedParamResults() { 97 | Collection data = Collections 98 | .singletonList(new BenchmarkResult(null, data())); 99 | String result = output(new RunResult(params("a=b"), data), new RunResult(params("a=e", "c=d"), data)); 100 | assertThat(result) 101 | .containsSubsequence("class, method, a, c, median, mean, range", "Foo, exec, b, ,", "e, d"); 102 | } 103 | 104 | @Test 105 | void writeMixedSecondaryResults() { 106 | Collection data = Collections 107 | .singletonList(new BenchmarkResult(null, data())); 108 | Collection seconds = Collections 109 | .singletonList(new BenchmarkResult(null, data("bar", "spam"))); 110 | String result = output(new RunResult(params(), data), new RunResult(params(), seconds)); 111 | assertThat(result) 112 | .containsSubsequence("class, method, bar, spam, median, mean, range", "Foo, exec, , ", 113 | "Foo, exec, " + ScoreFormatter.format(1.000)); 114 | } 115 | 116 | private BenchmarkParams params(String... workloads) { 117 | WorkloadParams workload = new WorkloadParams(); 118 | for (int i = 0; i < workloads.length; i++) { 119 | String pair = workloads[i]; 120 | String key = pair; 121 | String value = ""; 122 | if (pair.contains("=")) { 123 | key = pair.split("=")[0]; 124 | value = pair.split("=")[1].trim(); 125 | workload.put(key, value, i); 126 | } 127 | } 128 | return new BenchmarkParams("com.example.Foo.exec", "bar", true, 1, new int[]{1}, Collections 129 | .singletonList("thread"), 1, 0, 130 | null, null, Mode.AverageTime, workload, TimeUnit.MILLISECONDS, 1, "", Collections 131 | .emptyList(), "1.8", "JDK", 132 | "1.8", "1.21", TimeValue.NONE); 133 | } 134 | 135 | private static Collection data(String... seconds) { 136 | IterationResult result = new IterationResult(null, null, null); 137 | result.addResult(new AverageTimeResult(ResultRole.PRIMARY, "foo", 15, 300000000, TimeUnit.MILLISECONDS)); 138 | for (String label : seconds) { 139 | result.addResult(new AverageTimeResult(ResultRole.SECONDARY, label, 1, 1000000, TimeUnit.MILLISECONDS)); 140 | } 141 | return Collections.singletonList(result); 142 | } 143 | 144 | private String output(RunResult... runResult) { 145 | OutputStream stream = new ByteArrayOutputStream(); 146 | OutputFormat output = OutputFormatFactory 147 | .createFormatInstance(new PrintStream(stream), VerboseMode.NORMAL); 148 | factory.forUri("sysout").write(output, new BenchmarkResults(MetaData.none(), Arrays.asList(runResult))); 149 | return stream.toString(); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit4/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | com.github.mp911de.microbenchmark-runner 9 | microbenchmark-runner-parent 10 | 0.6.0.BUILD-SNAPSHOT 11 | 12 | 13 | microbenchmark-runner-junit4 14 | 15 | 16 | 17 | 18 | com.github.mp911de.microbenchmark-runner 19 | microbenchmark-runner-core 20 | ${project.version} 21 | 22 | 23 | 24 | junit 25 | junit 26 | 27 | 28 | 29 | org.openjdk.jmh 30 | jmh-generator-annprocess 31 | 32 | 33 | 34 | org.assertj 35 | assertj-core 36 | 37 | 38 | 39 | org.junit.jupiter 40 | junit-jupiter-api 41 | test 42 | 43 | 44 | 45 | org.junit.jupiter 46 | junit-jupiter-engine 47 | test 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit4/src/test/java/jmh/mbr/junit4/MicrobenchmarkUnitTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit4; 11 | 12 | import static org.assertj.core.api.Assertions.*; 13 | 14 | import org.junit.jupiter.api.Test; 15 | import org.junit.runner.Description; 16 | import org.junit.runners.model.InitializationError; 17 | 18 | class MicrobenchmarkUnitTests { 19 | 20 | @Test 21 | void shouldDescribeParametrizedBenchmark() throws InitializationError { 22 | 23 | Microbenchmark runner = new Microbenchmark(ParametrizedBenchmark.class); 24 | Description description = runner.getDescription(); 25 | 26 | assertThat(description.getTestClass()).isEqualTo(ParametrizedBenchmark.class); 27 | assertThat(description.getMethodName()).isNull(); 28 | assertThat(description.getChildren()).hasSize(2); 29 | 30 | Description fixture = description.getChildren().get(0); 31 | 32 | assertThat(fixture.getTestClass()).isNull(); 33 | assertThat(fixture.getMethodName()).isNull(); 34 | assertThat(fixture.getDisplayName()).isEqualTo("[foo=a]"); 35 | assertThat(fixture.getChildren()).hasSize(1); 36 | 37 | Description method = fixture.getChildren().get(0); 38 | 39 | assertThat(method.getTestClass()).isEqualTo(ParametrizedBenchmark.class); 40 | assertThat(method.getMethodName()).isEqualTo("foo"); 41 | } 42 | 43 | @Test 44 | void shouldDescribeSimpleBenchmark() throws InitializationError { 45 | 46 | Microbenchmark runner = new Microbenchmark(SimpleBenchmark.class); 47 | Description description = runner.getDescription(); 48 | 49 | assertThat(description.getTestClass()).isEqualTo(SimpleBenchmark.class); 50 | assertThat(description.getMethodName()).isNull(); 51 | assertThat(description.getChildren()).hasSize(1); 52 | 53 | Description method = description.getChildren().get(0); 54 | 55 | assertThat(method.getTestClass()).isEqualTo(SimpleBenchmark.class); 56 | assertThat(method.getMethodName()).isEqualTo("foo"); 57 | assertThat(method.getChildren()).isEmpty(); 58 | } 59 | 60 | @Test 61 | void shouldDescribePartiallyParametrizedBenchmark() throws InitializationError { 62 | 63 | Microbenchmark runner = new Microbenchmark(PartiallyParametrizedBenchmark.class); 64 | Description description = runner.getDescription(); 65 | 66 | assertThat(description.getTestClass()).isEqualTo(PartiallyParametrizedBenchmark.class); 67 | assertThat(description.getMethodName()).isNull(); 68 | assertThat(description.getChildren()).hasSize(3); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit4/src/test/java/jmh/mbr/junit4/ParametrizedBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit4; 11 | 12 | import org.junit.runner.RunWith; 13 | import org.openjdk.jmh.annotations.Benchmark; 14 | import org.openjdk.jmh.annotations.Fork; 15 | import org.openjdk.jmh.annotations.Measurement; 16 | import org.openjdk.jmh.annotations.Param; 17 | import org.openjdk.jmh.annotations.Scope; 18 | import org.openjdk.jmh.annotations.State; 19 | import org.openjdk.jmh.annotations.Warmup; 20 | 21 | @Warmup(iterations = 1, time = 1) 22 | @Measurement(iterations = 1, time = 1) 23 | @Fork(value = 1, warmups = 1) 24 | @State(Scope.Benchmark) 25 | @RunWith(Microbenchmark.class) 26 | public class ParametrizedBenchmark { 27 | 28 | @Param({ "a", "b" }) String foo; 29 | 30 | @Benchmark 31 | public void foo() {} 32 | } 33 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit4/src/test/java/jmh/mbr/junit4/PartiallyParametrizedBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit4; 11 | 12 | import org.junit.runner.RunWith; 13 | import org.openjdk.jmh.annotations.Benchmark; 14 | import org.openjdk.jmh.annotations.Fork; 15 | import org.openjdk.jmh.annotations.Measurement; 16 | import org.openjdk.jmh.annotations.Param; 17 | import org.openjdk.jmh.annotations.Scope; 18 | import org.openjdk.jmh.annotations.State; 19 | import org.openjdk.jmh.annotations.Warmup; 20 | 21 | @Warmup(iterations = 1, time = 1) 22 | @Measurement(iterations = 1, time = 1) 23 | @Fork(value = 1, warmups = 1) 24 | @RunWith(Microbenchmark.class) 25 | public class PartiallyParametrizedBenchmark { 26 | 27 | @State(Scope.Benchmark) 28 | public static class ParamState { 29 | @Param({ "a", "b" }) String foo; 30 | } 31 | 32 | @Benchmark 33 | public void foo() {} 34 | 35 | @Benchmark 36 | public void bar(ParamState paramState) {} 37 | } 38 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit4/src/test/java/jmh/mbr/junit4/SimpleBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit4; 11 | 12 | import org.junit.runner.RunWith; 13 | import org.openjdk.jmh.annotations.Benchmark; 14 | import org.openjdk.jmh.annotations.Fork; 15 | import org.openjdk.jmh.annotations.Measurement; 16 | import org.openjdk.jmh.annotations.Scope; 17 | import org.openjdk.jmh.annotations.State; 18 | import org.openjdk.jmh.annotations.Warmup; 19 | 20 | @RunWith(Microbenchmark.class) 21 | public class SimpleBenchmark { 22 | 23 | @Benchmark 24 | public void foo() {} 25 | } 26 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5-smoke-tests/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | microbenchmark-runner-parent 7 | com.github.mp911de.microbenchmark-runner 8 | 0.6.0.BUILD-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | microbenchmark-runner-junit5-smoke-tests 13 | 14 | 15 | 16 | com.github.mp911de.microbenchmark-runner 17 | microbenchmark-runner-junit5 18 | ${project.parent.version} 19 | 20 | 21 | com.github.mp911de.microbenchmark-runner 22 | microbenchmark-runner-extras 23 | ${project.parent.version} 24 | 25 | 26 | org.openjdk.jmh 27 | jmh-generator-annprocess 28 | ${jmh.version} 29 | test 30 | 31 | 32 | org.elasticsearch.client 33 | elasticsearch-rest-high-level-client 34 | 7.5.0 35 | test 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5-smoke-tests/src/test/java/jmh/mbr/junit5/InnerStateSmokeTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * https://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5; 11 | 12 | import java.util.concurrent.TimeUnit; 13 | 14 | import org.junit.platform.commons.annotation.Testable; 15 | import org.openjdk.jmh.annotations.AuxCounters; 16 | import org.openjdk.jmh.annotations.AuxCounters.Type; 17 | import org.openjdk.jmh.annotations.Benchmark; 18 | import org.openjdk.jmh.annotations.Measurement; 19 | import org.openjdk.jmh.annotations.Param; 20 | import org.openjdk.jmh.annotations.Scope; 21 | import org.openjdk.jmh.annotations.State; 22 | import org.openjdk.jmh.annotations.Warmup; 23 | 24 | @Warmup(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS) 25 | @Measurement(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS) 26 | @Microbenchmark 27 | public class InnerStateSmokeTests { 28 | 29 | @Benchmark 30 | @Testable 31 | public double log1p(MainState state) { 32 | return Math.log1p(state.getValue()); 33 | } 34 | 35 | @State(Scope.Thread) 36 | @AuxCounters(Type.EVENTS) 37 | public static class MainState { 38 | 39 | public enum Sample { 40 | one, two; 41 | } 42 | 43 | @Param 44 | private Sample sample = Sample.one; 45 | 46 | public double getValue() { 47 | return sample == Sample.one ? Math.PI : Math.E; 48 | } 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5-smoke-tests/src/test/java/jmh/mbr/junit5/ResultsWriterSmokeTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2020 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * https://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5; 11 | 12 | import java.util.concurrent.TimeUnit; 13 | 14 | import org.junit.platform.commons.annotation.Testable; 15 | import org.openjdk.jmh.annotations.Benchmark; 16 | import org.openjdk.jmh.annotations.Measurement; 17 | import org.openjdk.jmh.annotations.Scope; 18 | import org.openjdk.jmh.annotations.State; 19 | import org.openjdk.jmh.annotations.Warmup; 20 | 21 | @Microbenchmark 22 | @State(Scope.Thread) 23 | public class ResultsWriterSmokeTests { 24 | 25 | double x1 = Math.PI; 26 | 27 | @Benchmark 28 | @Warmup(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS) 29 | @Measurement(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS) 30 | @Testable 31 | public double log() { 32 | return Math.log(x1); 33 | } 34 | 35 | @Benchmark 36 | @Warmup(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS) 37 | @Measurement(iterations = 5, time = 100, timeUnit = TimeUnit.MILLISECONDS) 38 | @Testable 39 | public double log10() { 40 | return Math.log10(x1); 41 | } 42 | 43 | @Benchmark 44 | @Warmup(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS) 45 | @Measurement(iterations = 5, time = 100, timeUnit = TimeUnit.MILLISECONDS) 46 | @Testable 47 | public double log1p() { 48 | return Math.log1p(x1); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | com.github.mp911de.microbenchmark-runner 9 | microbenchmark-runner-parent 10 | 0.6.0.BUILD-SNAPSHOT 11 | 12 | 13 | microbenchmark-runner-junit5 14 | 15 | 16 | 17 | 18 | com.github.mp911de.microbenchmark-runner 19 | microbenchmark-runner-core 20 | ${project.version} 21 | 22 | 23 | 24 | org.junit.platform 25 | junit-platform-engine 26 | 27 | 28 | 29 | org.openjdk.jmh 30 | jmh-generator-annprocess 31 | 32 | 33 | 34 | org.assertj 35 | assertj-core 36 | 37 | 38 | 39 | org.junit.jupiter 40 | junit-jupiter-api 41 | 42 | 43 | 44 | org.junit.jupiter 45 | junit-jupiter-engine 46 | 47 | 48 | 49 | org.junit.platform 50 | junit-platform-launcher 51 | test 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/Microbenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5; 11 | 12 | import java.lang.annotation.Documented; 13 | import java.lang.annotation.ElementType; 14 | import java.lang.annotation.Retention; 15 | import java.lang.annotation.RetentionPolicy; 16 | import java.lang.annotation.Target; 17 | 18 | import org.junit.platform.commons.annotation.Testable; 19 | 20 | /** 21 | * {@code @Microbenchmark} is used to signal that the annotated type is a microbenchmark class that should be 22 | * ran using the Microbenchmark Runner. 23 | *

24 | * Benchmark classes executed with the Microbenchmark Runner can participate in tooling support without the need to 25 | * integrate with JMH-specific tool support. 26 | */ 27 | @Retention(RetentionPolicy.SOURCE) 28 | @Target(ElementType.TYPE) 29 | @Documented 30 | @Testable 31 | public @interface Microbenchmark { 32 | } 33 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/MicrobenchmarkEngine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5; 11 | 12 | import jmh.mbr.junit5.discovery.DiscoverySelectorResolver; 13 | import jmh.mbr.junit5.execution.JmhRunner; 14 | 15 | import java.util.Optional; 16 | 17 | import org.junit.jupiter.engine.config.DefaultJupiterConfiguration; 18 | import org.junit.jupiter.engine.config.JupiterConfiguration; 19 | import org.junit.jupiter.engine.extension.MutableExtensionRegistry; 20 | import org.junit.platform.engine.EngineDiscoveryRequest; 21 | import org.junit.platform.engine.ExecutionRequest; 22 | import org.junit.platform.engine.TestDescriptor; 23 | import org.junit.platform.engine.TestEngine; 24 | import org.junit.platform.engine.UniqueId; 25 | 26 | /** 27 | * Microbenchmark Runner Engine. 28 | */ 29 | public class MicrobenchmarkEngine implements TestEngine { 30 | 31 | public static final String ENGINE_ID = "microbenchmark-engine"; 32 | 33 | @Override 34 | public String getId() { 35 | return ENGINE_ID; 36 | } 37 | 38 | @Override 39 | public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { 40 | 41 | MicrobenchmarkEngineDescriptor engineDescriptor = new MicrobenchmarkEngineDescriptor(uniqueId); 42 | new DiscoverySelectorResolver() 43 | .resolveSelectors(discoveryRequest, engineDescriptor); 44 | return engineDescriptor; 45 | } 46 | 47 | @Override 48 | public void execute(ExecutionRequest request) { 49 | 50 | JupiterConfiguration jupiterConfiguration = new DefaultJupiterConfiguration(request 51 | .getConfigurationParameters(), request.getOutputDirectoryProvider()); 52 | MutableExtensionRegistry extensionRegistry = MutableExtensionRegistry 53 | .createRegistryWithDefaultExtensions(jupiterConfiguration); 54 | 55 | JupiterConfiguration configuration = new DefaultJupiterConfiguration(request.getConfigurationParameters(), request.getOutputDirectoryProvider()); 56 | new JmhRunner(configuration, extensionRegistry) 57 | .execute(request.getRootTestDescriptor(), request 58 | .getEngineExecutionListener()); 59 | } 60 | 61 | @Override 62 | public Optional getGroupId() { 63 | return Optional.of("com.github.mp911de.microbenchmark-runner"); 64 | } 65 | 66 | @Override 67 | public Optional getArtifactId() { 68 | return Optional.of("microbenchmark-runner-junit5"); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/MicrobenchmarkEngineDescriptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5; 11 | 12 | import org.junit.platform.engine.UniqueId; 13 | import org.junit.platform.engine.support.descriptor.EngineDescriptor; 14 | 15 | /** 16 | * {@link EngineDescriptor} for Microbenchmark Runner. 17 | */ 18 | class MicrobenchmarkEngineDescriptor extends EngineDescriptor { 19 | 20 | MicrobenchmarkEngineDescriptor(UniqueId uniqueId) { 21 | super(uniqueId, "Microbenchmark Runner"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/descriptor/AbstractBenchmarkDescriptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.descriptor; 11 | 12 | import java.util.Collections; 13 | import java.util.Set; 14 | 15 | import org.junit.jupiter.api.extension.ExtensionContext; 16 | import org.junit.jupiter.engine.config.JupiterConfiguration; 17 | import org.junit.jupiter.engine.extension.ExtensionRegistry; 18 | import org.junit.jupiter.engine.extension.MutableExtensionRegistry; 19 | import org.junit.platform.engine.EngineExecutionListener; 20 | import org.junit.platform.engine.TestSource; 21 | import org.junit.platform.engine.TestTag; 22 | import org.junit.platform.engine.UniqueId; 23 | import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; 24 | import org.junit.platform.engine.support.descriptor.ClassSource; 25 | import org.junit.platform.engine.support.descriptor.MethodSource; 26 | 27 | /** 28 | * Abstract base class for Benchmark descriptors. Exposes {@link TestTag tags} and allows contextual {@link org.junit.jupiter.api.extension.Extension} retrieval. 29 | */ 30 | public abstract class AbstractBenchmarkDescriptor extends AbstractTestDescriptor { 31 | 32 | private final Set tags; 33 | 34 | /** 35 | * Creates a new {@link AbstractBenchmarkDescriptor} given {@link UniqueId}, {@code displayName} and a {@link TestSource}. 36 | * 37 | * @param uniqueId the {@link UniqueId} for this descriptor. 38 | * @param displayName 39 | * @param source source this descriptor. 40 | */ 41 | public AbstractBenchmarkDescriptor(UniqueId uniqueId, String displayName, TestSource source) { 42 | super(uniqueId, displayName, source); 43 | 44 | Set tags = Collections.emptySet(); 45 | if (source instanceof ClassSource) { 46 | tags = DescriptorUtils.getTags(((ClassSource) source).getJavaClass()); 47 | } 48 | if (source instanceof MethodSource) { 49 | try { 50 | tags = DescriptorUtils 51 | .getTags(Class.forName(((MethodSource) source).getClassName())); 52 | } 53 | catch (ClassNotFoundException e) { 54 | throw new IllegalStateException(e); 55 | } 56 | } 57 | 58 | this.tags = tags; 59 | } 60 | 61 | @Override 62 | public Set getTags() { 63 | return tags; 64 | } 65 | 66 | /** 67 | * Creates a {@link ExtensionContext} for this descriptor containing scoped extensions. 68 | * 69 | * @param parent optional parent {@link ExtensionContext}. {@literal null} to use no parent so the resulting context serves as root {@link ExtensionContext}. 70 | * @param engineExecutionListener the listener. 71 | * @param configuration configuration parameters. 72 | * @return the {@link ExtensionContext} for this descriptor. 73 | */ 74 | public abstract ExtensionContext getExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener, JupiterConfiguration configuration); 75 | 76 | /** 77 | * Creates an {@link MutableExtensionRegistry} that contains extensions derived from the benchmark source (annotations on class/method level). 78 | * 79 | * @param parent the parent {@link MutableExtensionRegistry}. 80 | * @return the {@link ExtensionRegistry} derived from this descriptor. 81 | */ 82 | public abstract ExtensionRegistry getExtensionRegistry(MutableExtensionRegistry parent); 83 | } 84 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/descriptor/BenchmarkClassDescriptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.descriptor; 11 | 12 | import jmh.mbr.core.model.BenchmarkClass; 13 | 14 | import org.junit.jupiter.api.extension.ExtensionContext; 15 | import org.junit.jupiter.engine.config.JupiterConfiguration; 16 | import org.junit.jupiter.engine.extension.ExtensionRegistry; 17 | import org.junit.jupiter.engine.extension.MutableExtensionRegistry; 18 | import org.junit.platform.engine.EngineExecutionListener; 19 | import org.junit.platform.engine.UniqueId; 20 | import org.junit.platform.engine.support.descriptor.ClassSource; 21 | 22 | /** 23 | * {@link org.junit.platform.engine.TestDescriptor} for a {@link BenchmarkClass}. 24 | */ 25 | public class BenchmarkClassDescriptor extends AbstractBenchmarkDescriptor { 26 | 27 | private final BenchmarkClass benchmarkClass; 28 | 29 | public BenchmarkClassDescriptor(UniqueId uniqueId, BenchmarkClass benchmarkClass) { 30 | 31 | super(uniqueId, benchmarkClass.getJavaClass().getName(), ClassSource.from(benchmarkClass.getJavaClass())); 32 | this.benchmarkClass = benchmarkClass; 33 | } 34 | 35 | @Override 36 | public Type getType() { 37 | return Type.CONTAINER; 38 | } 39 | 40 | public BenchmarkClass getBenchmarkClass() { 41 | return benchmarkClass; 42 | } 43 | 44 | public Class getJavaClass() { 45 | return benchmarkClass.getJavaClass(); 46 | } 47 | 48 | @Override 49 | public ExtensionContext getExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener, JupiterConfiguration configuration) { 50 | return new BenchmarkClassExtensionContext(parent, engineExecutionListener, this, configuration); 51 | } 52 | 53 | @Override 54 | public ExtensionRegistry getExtensionRegistry(MutableExtensionRegistry parent) { 55 | return ExtensionUtils.populateNewExtensionRegistryFromExtendWithAnnotation(parent, getJavaClass()); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/descriptor/BenchmarkClassExtensionContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.descriptor; 11 | 12 | import java.lang.reflect.AnnotatedElement; 13 | import java.lang.reflect.Method; 14 | import java.util.Collections; 15 | import java.util.List; 16 | import java.util.Optional; 17 | 18 | import org.junit.jupiter.api.TestInstance.Lifecycle; 19 | import org.junit.jupiter.api.extension.ExtensionContext; 20 | import org.junit.jupiter.api.extension.TestInstances; 21 | import org.junit.jupiter.engine.config.JupiterConfiguration; 22 | import org.junit.platform.engine.EngineExecutionListener; 23 | import org.junit.platform.engine.support.hierarchical.Node.ExecutionMode; 24 | 25 | /** 26 | * {@link ExtensionContext} for a {@link BenchmarkClassDescriptor}. 27 | */ 28 | class BenchmarkClassExtensionContext extends AbstractExtensionContext { 29 | 30 | BenchmarkClassExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener, BenchmarkClassDescriptor testDescriptor, JupiterConfiguration configuration) { 31 | super(parent, engineExecutionListener, testDescriptor, configuration); 32 | } 33 | 34 | @Override 35 | public Optional getElement() { 36 | return Optional.of(getBenchmarkDescriptor().getJavaClass()); 37 | } 38 | 39 | @Override 40 | public Optional> getTestClass() { 41 | return Optional.of(getBenchmarkDescriptor().getJavaClass()); 42 | } 43 | 44 | @Override 45 | public Optional getTestInstanceLifecycle() { 46 | return Optional.empty(); 47 | } 48 | 49 | @Override 50 | public Optional getTestInstance() { 51 | return Optional.empty(); 52 | } 53 | 54 | @Override 55 | public Optional getTestInstances() { 56 | return Optional.empty(); 57 | } 58 | 59 | @Override 60 | public Optional getTestMethod() { 61 | return Optional.empty(); 62 | } 63 | 64 | @Override 65 | public Optional getExecutionException() { 66 | return Optional.empty(); 67 | } 68 | 69 | @Override 70 | protected ExecutionMode getPlatformExecutionMode() { 71 | return ExecutionMode.SAME_THREAD; 72 | } 73 | 74 | @Override 75 | public List> getEnclosingTestClasses() { 76 | return Collections.emptyList(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/descriptor/BenchmarkFixtureDescriptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.descriptor; 11 | 12 | import jmh.mbr.core.model.BenchmarkFixture; 13 | import jmh.mbr.core.model.BenchmarkMethod; 14 | 15 | import java.util.Set; 16 | 17 | import org.junit.jupiter.api.extension.ExtensionContext; 18 | import org.junit.jupiter.engine.config.JupiterConfiguration; 19 | import org.junit.jupiter.engine.extension.ExtensionRegistry; 20 | import org.junit.jupiter.engine.extension.MutableExtensionRegistry; 21 | import org.junit.platform.engine.EngineExecutionListener; 22 | import org.junit.platform.engine.TestTag; 23 | import org.junit.platform.engine.UniqueId; 24 | import org.junit.platform.engine.support.descriptor.MethodSource; 25 | 26 | /** 27 | * {@link org.junit.platform.engine.TestDescriptor} for a {@link BenchmarkFixture}. 28 | */ 29 | public class BenchmarkFixtureDescriptor extends AbstractBenchmarkDescriptor { 30 | 31 | private final BenchmarkFixture fixture; 32 | private final Set tags; 33 | 34 | public BenchmarkFixtureDescriptor(UniqueId uniqueId, BenchmarkMethod method, BenchmarkFixture fixture) { 35 | super(uniqueId, fixture.getDisplayName(), MethodSource.from(method.getMethod())); 36 | this.fixture = fixture; 37 | this.tags = DescriptorUtils.getTags(method.getDeclaringClass()); 38 | } 39 | 40 | @Override 41 | public Set getTags() { 42 | return tags; 43 | } 44 | 45 | @Override 46 | public Type getType() { 47 | return Type.TEST; 48 | } 49 | 50 | @Override 51 | public ExtensionContext getExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener, JupiterConfiguration configuration) { 52 | throw new UnsupportedOperationException(); 53 | } 54 | 55 | @Override 56 | public ExtensionRegistry getExtensionRegistry(MutableExtensionRegistry parent) { 57 | throw new UnsupportedOperationException(); 58 | } 59 | 60 | public BenchmarkFixture getFixture() { 61 | return fixture; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/descriptor/BenchmarkMethodDescriptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.descriptor; 11 | 12 | import jmh.mbr.core.model.BenchmarkMethod; 13 | import jmh.mbr.core.model.MethodAware; 14 | 15 | import java.lang.reflect.Method; 16 | 17 | import org.junit.jupiter.api.extension.ExtensionContext; 18 | import org.junit.jupiter.engine.config.JupiterConfiguration; 19 | import org.junit.jupiter.engine.extension.ExtensionRegistry; 20 | import org.junit.jupiter.engine.extension.MutableExtensionRegistry; 21 | import org.junit.platform.commons.util.ClassUtils; 22 | import org.junit.platform.engine.EngineExecutionListener; 23 | import org.junit.platform.engine.UniqueId; 24 | import org.junit.platform.engine.support.descriptor.MethodSource; 25 | 26 | /** 27 | * {@link org.junit.platform.engine.TestDescriptor} for a {@link BenchmarkMethod}. 28 | */ 29 | public class BenchmarkMethodDescriptor extends AbstractBenchmarkDescriptor implements MethodAware { 30 | 31 | private final BenchmarkMethod method; 32 | 33 | public BenchmarkMethodDescriptor(UniqueId uniqueId, BenchmarkMethod method) { 34 | super(uniqueId, generateDefaultDisplayName(method), 35 | MethodSource.from(method.getDeclaringClass(), method.getMethod())); 36 | this.method = method; 37 | } 38 | 39 | @Override 40 | public Type getType() { 41 | return Type.TEST; 42 | } 43 | 44 | @Override 45 | public String getLegacyReportingName() { 46 | return generateDefaultDisplayName(method.getMethod()); 47 | } 48 | 49 | @Override 50 | public Method getMethod() { 51 | return method.getMethod(); 52 | } 53 | 54 | @Override 55 | public boolean isUnderlyingMethod(Method method) { 56 | return this.method.getMethod().equals(method); 57 | } 58 | 59 | @Override 60 | public ExtensionContext getExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener, JupiterConfiguration configuration) { 61 | return new BenchmarkMethodExtensionContext(parent, engineExecutionListener, this, configuration, this); 62 | } 63 | 64 | @Override 65 | public ExtensionRegistry getExtensionRegistry(MutableExtensionRegistry parent) { 66 | return ExtensionUtils.populateNewExtensionRegistryFromExtendWithAnnotation(parent, getMethod()); 67 | } 68 | 69 | public BenchmarkMethod getBenchmarkMethod() { 70 | return method; 71 | } 72 | 73 | public static UniqueId createUniqueId(UniqueId uniqueId, BenchmarkMethod benchmarkMethod) { 74 | return uniqueId.append("method", describeMethodId(benchmarkMethod.getMethod())); 75 | } 76 | 77 | public static String describeMethodId(Method method) { 78 | return String.format("%s(%s)", method.getName(), ClassUtils.nullSafeToString(method.getParameterTypes())); 79 | } 80 | 81 | private static String generateDefaultDisplayName(BenchmarkMethod benchmarkMethod) { 82 | return generateDefaultDisplayName(benchmarkMethod.getMethod()); 83 | } 84 | 85 | private static String generateDefaultDisplayName(Method method) { 86 | return String.format("%s(%s)", method.getName(), 87 | ClassUtils.nullSafeToString(Class::getSimpleName, method.getParameterTypes())); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/descriptor/BenchmarkMethodExtensionContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.descriptor; 11 | 12 | import jmh.mbr.core.model.MethodAware; 13 | 14 | import java.lang.reflect.AnnotatedElement; 15 | import java.lang.reflect.Method; 16 | import java.util.Collections; 17 | import java.util.List; 18 | import java.util.Optional; 19 | 20 | import org.junit.jupiter.api.TestInstance.Lifecycle; 21 | import org.junit.jupiter.api.extension.ExtensionContext; 22 | import org.junit.jupiter.api.extension.TestInstances; 23 | import org.junit.jupiter.engine.config.JupiterConfiguration; 24 | import org.junit.platform.engine.EngineExecutionListener; 25 | import org.junit.platform.engine.TestDescriptor; 26 | import org.junit.platform.engine.support.hierarchical.Node.ExecutionMode; 27 | 28 | /** 29 | * {@link ExtensionContext} for a {@link AbstractBenchmarkDescriptor} that is {@link MethodAware}. 30 | */ 31 | class BenchmarkMethodExtensionContext extends AbstractExtensionContext { 32 | 33 | private final MethodAware methodAware; 34 | 35 | BenchmarkMethodExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener, MethodAware methodAware, JupiterConfiguration configuration, TestDescriptor testDescriptor) { 36 | super(parent, engineExecutionListener, (AbstractBenchmarkDescriptor) methodAware, configuration); 37 | this.methodAware = methodAware; 38 | } 39 | 40 | @Override 41 | public Optional getElement() { 42 | return Optional.of(methodAware.getMethod()); 43 | } 44 | 45 | @Override 46 | public Optional> getTestClass() { 47 | return Optional.of(methodAware.getMethod().getDeclaringClass()); 48 | } 49 | 50 | @Override 51 | public Optional getTestInstanceLifecycle() { 52 | return Optional.empty(); 53 | } 54 | 55 | @Override 56 | public Optional getTestInstance() { 57 | return Optional.empty(); 58 | } 59 | 60 | @Override 61 | public Optional getTestInstances() { 62 | return Optional.empty(); 63 | } 64 | 65 | @Override 66 | public Optional getTestMethod() { 67 | return Optional.of(methodAware.getMethod()); 68 | } 69 | 70 | @Override 71 | public Optional getExecutionException() { 72 | return Optional.empty(); 73 | } 74 | 75 | @Override 76 | protected ExecutionMode getPlatformExecutionMode() { 77 | return ExecutionMode.SAME_THREAD; 78 | } 79 | 80 | @Override 81 | public List> getEnclosingTestClasses() { 82 | return Collections.emptyList(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/descriptor/DescriptorUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.descriptor; 11 | 12 | import java.lang.reflect.AnnotatedElement; 13 | import java.util.Collections; 14 | import java.util.LinkedHashSet; 15 | import java.util.Set; 16 | import java.util.stream.Collectors; 17 | 18 | import org.junit.jupiter.api.Tag; 19 | import org.junit.platform.commons.logging.Logger; 20 | import org.junit.platform.commons.logging.LoggerFactory; 21 | import org.junit.platform.commons.util.AnnotationUtils; 22 | import org.junit.platform.engine.TestTag; 23 | 24 | /** 25 | * Utilities for {@link org.junit.platform.engine.TestDescriptor}. 26 | */ 27 | class DescriptorUtils { 28 | 29 | private static final Logger logger = LoggerFactory.getLogger(BenchmarkClassDescriptor.class); 30 | 31 | private DescriptorUtils() { 32 | } 33 | 34 | protected static Set getTags(AnnotatedElement element) { 35 | 36 | return AnnotationUtils.findRepeatableAnnotations(element, Tag.class).stream().map(Tag::value).filter((tag) -> { 37 | 38 | boolean isValid = TestTag.isValid(tag); 39 | if (!isValid) { 40 | logger.warn(() -> String.format("Configuration error: invalid tag syntax in @Tag(\"%s\") declaration on [%s]. Tag will be ignored.", tag, element)); 41 | } 42 | 43 | return isValid; 44 | }).map(TestTag::create) 45 | .collect(Collectors.collectingAndThen(Collectors.toCollection(LinkedHashSet::new), Collections::unmodifiableSet)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/descriptor/ExtensionUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.descriptor; 11 | 12 | import java.lang.reflect.AnnotatedElement; 13 | import java.util.Arrays; 14 | import java.util.List; 15 | import java.util.stream.Collectors; 16 | 17 | import org.junit.jupiter.api.extension.ExtendWith; 18 | import org.junit.jupiter.api.extension.Extension; 19 | import org.junit.jupiter.engine.extension.ExtensionRegistry; 20 | import org.junit.jupiter.engine.extension.MutableExtensionRegistry; 21 | import org.junit.platform.commons.util.AnnotationUtils; 22 | 23 | /** 24 | * Utility to collect extension classes and create a {@link ExtensionRegistry}. 25 | */ 26 | abstract class ExtensionUtils { 27 | 28 | private ExtensionUtils() { 29 | } 30 | 31 | static ExtensionRegistry populateNewExtensionRegistryFromExtendWithAnnotation(MutableExtensionRegistry parentRegistry, 32 | AnnotatedElement annotatedElement) { 33 | 34 | List> extensionTypes = AnnotationUtils 35 | .findRepeatableAnnotations(annotatedElement, ExtendWith.class) 36 | .stream() 37 | .map(ExtendWith::value) 38 | .flatMap(Arrays::stream) 39 | .collect(Collectors.toList()); 40 | 41 | return MutableExtensionRegistry 42 | .createRegistryFrom(parentRegistry, extensionTypes.stream()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/descriptor/ParametrizedBenchmarkMethodDescriptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.descriptor; 11 | 12 | import jmh.mbr.core.model.BenchmarkMethod; 13 | import jmh.mbr.core.model.MethodAware; 14 | import jmh.mbr.core.model.ParametrizedBenchmarkMethod; 15 | 16 | import java.lang.reflect.Method; 17 | 18 | import org.junit.jupiter.api.extension.ExtensionContext; 19 | import org.junit.jupiter.engine.config.JupiterConfiguration; 20 | import org.junit.jupiter.engine.extension.ExtensionRegistry; 21 | import org.junit.jupiter.engine.extension.MutableExtensionRegistry; 22 | import org.junit.platform.commons.util.ClassUtils; 23 | import org.junit.platform.engine.EngineExecutionListener; 24 | import org.junit.platform.engine.UniqueId; 25 | import org.junit.platform.engine.support.descriptor.MethodSource; 26 | 27 | /** 28 | * {@link org.junit.platform.engine.TestDescriptor} for a parametrized {@link BenchmarkMethod} with fixtures. 29 | */ 30 | public class ParametrizedBenchmarkMethodDescriptor extends AbstractBenchmarkDescriptor implements MethodAware { 31 | 32 | private final BenchmarkMethod method; 33 | private final ParametrizedBenchmarkMethod parametrizedMethod; 34 | 35 | public ParametrizedBenchmarkMethodDescriptor(UniqueId uniqueId, ParametrizedBenchmarkMethod parametrizedMethod) { 36 | this(uniqueId, parametrizedMethod.getDescriptor(), parametrizedMethod); 37 | } 38 | 39 | private ParametrizedBenchmarkMethodDescriptor(UniqueId uniqueId, BenchmarkMethod benchmarkMethod, 40 | ParametrizedBenchmarkMethod parametrizedMethod) { 41 | super(uniqueId, generateDefaultDisplayName(benchmarkMethod.getMethod()), 42 | MethodSource.from(benchmarkMethod.getDeclaringClass(), benchmarkMethod 43 | .getMethod())); 44 | this.method = benchmarkMethod; 45 | this.parametrizedMethod = parametrizedMethod; 46 | } 47 | 48 | @Override 49 | public Type getType() { 50 | return Type.CONTAINER; 51 | } 52 | 53 | @Override 54 | public String getLegacyReportingName() { 55 | return generateDefaultDisplayName(method.getMethod()); 56 | } 57 | 58 | @Override 59 | public Method getMethod() { 60 | return method.getMethod(); 61 | } 62 | 63 | @Override 64 | public boolean isUnderlyingMethod(Method method) { 65 | return this.method.getMethod().equals(method); 66 | } 67 | 68 | @Override 69 | public ExtensionContext getExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener, JupiterConfiguration configuration) { 70 | return new BenchmarkMethodExtensionContext(parent, engineExecutionListener, this, configuration, this); 71 | } 72 | 73 | @Override 74 | public ExtensionRegistry getExtensionRegistry(MutableExtensionRegistry parent) { 75 | return ExtensionUtils 76 | .populateNewExtensionRegistryFromExtendWithAnnotation(parent, getMethod()); 77 | } 78 | 79 | public ParametrizedBenchmarkMethod getParametrizedMethod() { 80 | return parametrizedMethod; 81 | } 82 | 83 | public BenchmarkMethod getBenchmarkMethod() { 84 | return method; 85 | } 86 | 87 | private static String generateDefaultDisplayName(Method testMethod) { 88 | return String.format("%s(%s)", testMethod.getName(), 89 | ClassUtils.nullSafeToString(Class::getSimpleName, testMethod 90 | .getParameterTypes())); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/discovery/BenchmarkContainerResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.discovery; 11 | 12 | import jmh.mbr.core.model.BenchmarkClass; 13 | import jmh.mbr.core.model.BenchmarkDescriptorFactory; 14 | import jmh.mbr.junit5.descriptor.BenchmarkClassDescriptor; 15 | import jmh.mbr.junit5.discovery.predicates.IsBenchmarkClass; 16 | 17 | import java.lang.reflect.AnnotatedElement; 18 | import java.util.Collections; 19 | import java.util.Optional; 20 | import java.util.Set; 21 | 22 | import org.junit.platform.commons.util.ReflectionUtils; 23 | import org.junit.platform.engine.TestDescriptor; 24 | import org.junit.platform.engine.UniqueId; 25 | 26 | /** 27 | * {@link ElementResolver} for test containers. Containers are based on {@link Class classes} that contain 28 | * {@code Benchmark} methods. 29 | * 30 | * @see IsBenchmarkClass 31 | */ 32 | class BenchmarkContainerResolver implements ElementResolver { 33 | 34 | private static final String SEGMENT_TYPE = "class"; 35 | 36 | BenchmarkContainerResolver() {} 37 | 38 | @Override 39 | public Set resolveElement(AnnotatedElement element, TestDescriptor parent) { 40 | 41 | if (!(element instanceof Class)) { 42 | return Collections.emptySet(); 43 | } 44 | 45 | Class clazz = (Class) element; 46 | if (!isPotentialCandidate(clazz)) { 47 | return Collections.emptySet(); 48 | } 49 | 50 | UniqueId uniqueId = createUniqueId(clazz, parent); 51 | return Collections.singleton(resolveClass(clazz, uniqueId)); 52 | } 53 | 54 | @Override 55 | public Optional resolveUniqueId(UniqueId.Segment segment, TestDescriptor parent) { 56 | 57 | if (!segment.getType().equals(SEGMENT_TYPE)) { 58 | return Optional.empty(); 59 | } 60 | 61 | if (!requiredParentType().isInstance(parent)) { 62 | return Optional.empty(); 63 | } 64 | 65 | String className = getClassName(parent, segment.getValue()); 66 | 67 | Optional> optionalContainerClass = ReflectionUtils.loadClass(className); 68 | if (!optionalContainerClass.isPresent()) { 69 | return Optional.empty(); 70 | } 71 | 72 | Class containerClass = optionalContainerClass.get(); 73 | if (!isPotentialCandidate(containerClass)) { 74 | return Optional.empty(); 75 | } 76 | 77 | UniqueId uniqueId = createUniqueId(containerClass, parent); 78 | return Optional.of(resolveClass(containerClass, uniqueId)); 79 | } 80 | 81 | private Class requiredParentType() { 82 | return TestDescriptor.class; 83 | } 84 | 85 | private String getClassName(TestDescriptor parent, String segmentValue) { 86 | return segmentValue; 87 | } 88 | 89 | private boolean isPotentialCandidate(Class element) { 90 | return IsBenchmarkClass.INSTANCE.test(element); 91 | } 92 | 93 | private UniqueId createUniqueId(Class benchmarkClass, TestDescriptor parent) { 94 | return parent.getUniqueId().append(SEGMENT_TYPE, benchmarkClass.getName()); 95 | } 96 | 97 | private TestDescriptor resolveClass(Class benchmarkClass, UniqueId uniqueId) { 98 | 99 | BenchmarkClass descriptor = BenchmarkDescriptorFactory.create(benchmarkClass).createDescriptor(); 100 | 101 | return new BenchmarkClassDescriptor(uniqueId, descriptor); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/discovery/BenchmarkFixtureResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.discovery; 11 | 12 | import jmh.mbr.core.model.ParametrizedBenchmarkMethod; 13 | import jmh.mbr.junit5.descriptor.BenchmarkFixtureDescriptor; 14 | import jmh.mbr.junit5.descriptor.ParametrizedBenchmarkMethodDescriptor; 15 | 16 | import java.lang.reflect.AnnotatedElement; 17 | import java.lang.reflect.Method; 18 | import java.util.Collections; 19 | import java.util.Optional; 20 | import java.util.Set; 21 | import java.util.stream.Collectors; 22 | 23 | import org.junit.platform.engine.TestDescriptor; 24 | import org.junit.platform.engine.UniqueId; 25 | import org.junit.platform.engine.UniqueId.Segment; 26 | 27 | /** 28 | * {@link ElementResolver} for {@link jmh.mbr.core.model.BenchmarkFixture fixtures}. 29 | */ 30 | class BenchmarkFixtureResolver implements ElementResolver { 31 | 32 | private static final String SEGMENT_TYPE = "fixture"; 33 | 34 | @Override 35 | public Set resolveElement(AnnotatedElement element, TestDescriptor parent) { 36 | 37 | if (!(element instanceof Method)) { 38 | return Collections.emptySet(); 39 | } 40 | 41 | if (!(parent instanceof ParametrizedBenchmarkMethodDescriptor)) { 42 | return Collections.emptySet(); 43 | } 44 | 45 | ParametrizedBenchmarkMethodDescriptor parentDescriptor = (ParametrizedBenchmarkMethodDescriptor) parent; 46 | 47 | Method method = (Method) element; 48 | 49 | if (!parentDescriptor.isUnderlyingMethod(method)) { 50 | return Collections.emptySet(); 51 | } 52 | 53 | return findFixtures(parent.getUniqueId(), parentDescriptor.getParametrizedMethod()); 54 | } 55 | 56 | @Override 57 | public Optional resolveUniqueId(Segment segment, TestDescriptor parent) { 58 | 59 | if (!segment.getType().equals(SEGMENT_TYPE)) { 60 | return Optional.empty(); 61 | } 62 | 63 | if (!(parent instanceof ParametrizedBenchmarkMethodDescriptor)) { 64 | return Optional.empty(); 65 | } 66 | 67 | ParametrizedBenchmarkMethodDescriptor parentDescriptor = (ParametrizedBenchmarkMethodDescriptor) parent; 68 | 69 | return findTestDescriptor(segment.getValue(), parentDescriptor.getUniqueId(), 70 | parentDescriptor.getParametrizedMethod()); 71 | } 72 | 73 | private Set findFixtures(UniqueId parentId, ParametrizedBenchmarkMethod descriptor) { 74 | 75 | return descriptor.getChildren().stream().map(it -> { 76 | 77 | UniqueId uniqueId = parentId.append(SEGMENT_TYPE, it.getDisplayName()); 78 | return new BenchmarkFixtureDescriptor(uniqueId, descriptor.getDescriptor(), it); 79 | }).collect(Collectors.toSet()); 80 | } 81 | 82 | private Optional findTestDescriptor(String segmentValue, UniqueId parentId, 83 | ParametrizedBenchmarkMethod parametrizedMethod) { 84 | 85 | return parametrizedMethod.getChildren().stream().filter(it -> { 86 | return it.getDisplayName().equals(segmentValue); 87 | }).map(it -> { 88 | 89 | UniqueId uniqueId = parentId.append(SEGMENT_TYPE, it.getDisplayName()); 90 | 91 | return (TestDescriptor) new BenchmarkFixtureDescriptor(uniqueId, parametrizedMethod.getDescriptor(), it); 92 | }).findFirst(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/discovery/BenchmarkMethodResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.discovery; 11 | 12 | import jmh.mbr.core.model.BenchmarkClass; 13 | import jmh.mbr.core.model.BenchmarkDescriptor; 14 | import jmh.mbr.core.model.BenchmarkMethod; 15 | import jmh.mbr.core.model.MethodAware; 16 | import jmh.mbr.core.model.ParametrizedBenchmarkMethod; 17 | import jmh.mbr.junit5.descriptor.BenchmarkClassDescriptor; 18 | import jmh.mbr.junit5.descriptor.BenchmarkMethodDescriptor; 19 | import jmh.mbr.junit5.descriptor.ParametrizedBenchmarkMethodDescriptor; 20 | 21 | import java.lang.reflect.AnnotatedElement; 22 | import java.lang.reflect.Method; 23 | import java.util.Collections; 24 | import java.util.Optional; 25 | import java.util.Set; 26 | 27 | import org.junit.platform.engine.TestDescriptor; 28 | import org.junit.platform.engine.UniqueId; 29 | import org.junit.platform.engine.UniqueId.Segment; 30 | 31 | /** 32 | * {@link ElementResolver} for {@code Benchmark} {@link Method methods}. 33 | */ 34 | class BenchmarkMethodResolver implements ElementResolver { 35 | 36 | private static final String SEGMENT_TYPE = "method"; 37 | 38 | @Override 39 | public Set resolveElement(AnnotatedElement element, TestDescriptor parent) { 40 | 41 | if (!(element instanceof Method)) { 42 | return Collections.emptySet(); 43 | } 44 | 45 | if (!(parent instanceof BenchmarkClassDescriptor)) { 46 | return Collections.emptySet(); 47 | } 48 | 49 | Method method = (Method) element; 50 | BenchmarkClassDescriptor classDescriptor = (BenchmarkClassDescriptor) parent; 51 | 52 | if (!method.getDeclaringClass().isAssignableFrom(classDescriptor.getJavaClass())) { 53 | return Collections.emptySet(); 54 | } 55 | 56 | return findMethod(parent.getUniqueId(), classDescriptor.getBenchmarkClass(), method).map(Collections::singleton) 57 | .orElseGet(Collections::emptySet); 58 | } 59 | 60 | @Override 61 | public Optional resolveUniqueId(Segment segment, TestDescriptor parent) { 62 | 63 | if (!segment.getType().equals(SEGMENT_TYPE)) { 64 | return Optional.empty(); 65 | } 66 | 67 | if (!(parent instanceof BenchmarkClassDescriptor)) { 68 | return Optional.empty(); 69 | } 70 | 71 | BenchmarkClassDescriptor descriptor = (BenchmarkClassDescriptor) parent; 72 | 73 | return findMethod(segment, parent.getUniqueId(), descriptor.getBenchmarkClass()); 74 | } 75 | 76 | private Optional findMethod(UniqueId parentId, BenchmarkClass benchmarkClass, Method method) { 77 | 78 | return benchmarkClass.getChildren().stream() // 79 | .filter(MethodAware.class::isInstance) // 80 | .filter(it -> ((MethodAware) it).isUnderlyingMethod(method)) // 81 | .map(it -> createDescriptor(parentId, it)).findFirst(); 82 | } 83 | 84 | private Optional findMethod(Segment segment, UniqueId parentId, BenchmarkClass benchmarkClass) { 85 | 86 | return benchmarkClass.getChildren().stream() // 87 | .filter(MethodAware.class::isInstance) // 88 | .filter(it -> { 89 | 90 | Method method = ((MethodAware) it).getMethod(); 91 | String id = BenchmarkMethodDescriptor.describeMethodId(method); 92 | 93 | return segment.getValue().equals(id); 94 | }) // 95 | .map(it -> createDescriptor(parentId, it)) // 96 | .findFirst(); 97 | } 98 | 99 | private TestDescriptor createDescriptor(UniqueId parentId, BenchmarkDescriptor it) { 100 | 101 | if (it instanceof ParametrizedBenchmarkMethod) { 102 | ParametrizedBenchmarkMethod parametrized = (ParametrizedBenchmarkMethod) it; 103 | UniqueId uniqueId = BenchmarkMethodDescriptor.createUniqueId(parentId, parametrized.getDescriptor()); 104 | 105 | return new ParametrizedBenchmarkMethodDescriptor(uniqueId, parametrized); 106 | } 107 | 108 | BenchmarkMethod benchmarkMethod = (BenchmarkMethod) it; 109 | UniqueId uniqueId = BenchmarkMethodDescriptor.createUniqueId(parentId, benchmarkMethod); 110 | 111 | return new BenchmarkMethodDescriptor(uniqueId, benchmarkMethod); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/discovery/DiscoveryFilterApplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.discovery; 11 | 12 | import jmh.mbr.junit5.descriptor.BenchmarkClassDescriptor; 13 | 14 | import java.util.function.Predicate; 15 | 16 | import org.junit.platform.engine.TestDescriptor; 17 | 18 | /** 19 | * Class for applying filters to all children of a {@link TestDescriptor}. 20 | */ 21 | class DiscoveryFilterApplier { 22 | 23 | void applyClassNamePredicate(Predicate classNamePredicate, TestDescriptor engineDescriptor) { 24 | TestDescriptor.Visitor filteringVisitor = descriptor -> { 25 | if (descriptor instanceof BenchmarkClassDescriptor 26 | && !includeClass((BenchmarkClassDescriptor) descriptor, classNamePredicate)) { 27 | descriptor.removeFromHierarchy(); 28 | } 29 | }; 30 | engineDescriptor.accept(filteringVisitor); 31 | } 32 | 33 | private boolean includeClass(BenchmarkClassDescriptor classTestDescriptor, Predicate classNamePredicate) { 34 | return classNamePredicate.test(classTestDescriptor.getJavaClass().getName()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/discovery/DiscoverySelectorResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.discovery; 11 | 12 | import jmh.mbr.junit5.discovery.predicates.IsBenchmarkClass; 13 | 14 | import org.junit.platform.commons.support.scanning.ClassFilter; 15 | import org.junit.platform.engine.ConfigurationParameters; 16 | import org.junit.platform.engine.EngineDiscoveryRequest; 17 | import org.junit.platform.engine.TestDescriptor; 18 | import org.junit.platform.engine.discovery.ClassSelector; 19 | import org.junit.platform.engine.discovery.ClasspathRootSelector; 20 | import org.junit.platform.engine.discovery.MethodSelector; 21 | import org.junit.platform.engine.discovery.ModuleSelector; 22 | import org.junit.platform.engine.discovery.PackageSelector; 23 | import org.junit.platform.engine.discovery.UniqueIdSelector; 24 | import org.junit.platform.engine.support.filter.ClasspathScanningSupport; 25 | 26 | /** 27 | * {@link JavaElementsResolver}-based discovery mechanism. Resolves {@link TestDescriptor descriptors} by introspecting 28 | * classes, methods, and {@link org.junit.platform.engine.UniqueId}. 29 | */ 30 | public class DiscoverySelectorResolver { 31 | 32 | public void resolveSelectors(EngineDiscoveryRequest request, TestDescriptor engineDescriptor) { 33 | 34 | ClassFilter classFilter = ClasspathScanningSupport.buildClassFilter(request, IsBenchmarkClass.INSTANCE); 35 | resolve(request, engineDescriptor, classFilter); 36 | filter(engineDescriptor, classFilter); 37 | pruneTree(engineDescriptor); 38 | } 39 | 40 | private void resolve(EngineDiscoveryRequest request, TestDescriptor engineDescriptor, ClassFilter classFilter) { 41 | 42 | JavaElementsResolver javaElementsResolver = createJavaElementsResolver(request.getConfigurationParameters(), 43 | engineDescriptor, classFilter); 44 | 45 | request.getSelectorsByType(ClasspathRootSelector.class).forEach(javaElementsResolver::resolveClasspathRoot); 46 | request.getSelectorsByType(ModuleSelector.class).forEach(javaElementsResolver::resolveModule); 47 | request.getSelectorsByType(PackageSelector.class).forEach(javaElementsResolver::resolvePackage); 48 | request.getSelectorsByType(ClassSelector.class).forEach(javaElementsResolver::resolveClass); 49 | request.getSelectorsByType(MethodSelector.class).forEach(javaElementsResolver::resolveMethod); 50 | request.getSelectorsByType(UniqueIdSelector.class).forEach(javaElementsResolver::resolveUniqueId); 51 | } 52 | 53 | private void filter(TestDescriptor engineDescriptor, ClassFilter classFilter) { 54 | new DiscoveryFilterApplier().applyClassNamePredicate(classFilter::match, engineDescriptor); 55 | } 56 | 57 | private void pruneTree(TestDescriptor rootDescriptor) { 58 | rootDescriptor.accept(TestDescriptor::prune); 59 | } 60 | 61 | private JavaElementsResolver createJavaElementsResolver(ConfigurationParameters configurationParameters, 62 | TestDescriptor engineDescriptor, ClassFilter classFilter) { 63 | return new JavaElementsResolver(engineDescriptor, classFilter, ElementResolvers.getResolvers()); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/discovery/ElementResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.discovery; 11 | 12 | import java.lang.reflect.AnnotatedElement; 13 | import java.util.Optional; 14 | import java.util.Set; 15 | 16 | import org.junit.platform.engine.TestDescriptor; 17 | import org.junit.platform.engine.UniqueId; 18 | 19 | interface ElementResolver { 20 | 21 | /** 22 | * Return a set of {@link TestDescriptor TestDescriptors} that can be resolved by this resolver. 23 | *

24 | * Returned set must be empty if {@code element} cannot be resolved. 25 | */ 26 | Set resolveElement(AnnotatedElement element, TestDescriptor parent); 27 | 28 | /** 29 | * Return an optional {@link TestDescriptor}. 30 | *

31 | * Return {@code Optional.empty()} if {@code segment} cannot be resolved. 32 | */ 33 | Optional resolveUniqueId(UniqueId.Segment segment, TestDescriptor parent); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/discovery/ElementResolvers.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.discovery; 11 | 12 | import java.util.LinkedHashSet; 13 | import java.util.Set; 14 | 15 | /** 16 | * Utility to obtain {@link ElementResolver}s. 17 | */ 18 | class ElementResolvers { 19 | 20 | /** 21 | * @return a {@link Set} of known {@link ElementResolver}s. 22 | */ 23 | public static Set getResolvers() { 24 | 25 | Set resolvers = new LinkedHashSet<>(); 26 | resolvers.add(new BenchmarkContainerResolver()); 27 | resolvers.add(new BenchmarkMethodResolver()); 28 | resolvers.add(new BenchmarkFixtureResolver()); 29 | 30 | return resolvers; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/discovery/predicates/IsBenchmarkClass.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.discovery.predicates; 11 | 12 | import java.util.Arrays; 13 | import java.util.function.Predicate; 14 | import java.util.stream.Stream; 15 | 16 | /** 17 | * {@link Predicate} to check whether a {@link Class} contains {@code @Benchmark} methods. 18 | * 19 | * @see IsBenchmarkMethod 20 | */ 21 | public enum IsBenchmarkClass implements Predicate> { 22 | 23 | INSTANCE; 24 | 25 | @Override 26 | public boolean test(Class theClass) { 27 | return Stream.concat(Arrays.stream(theClass.getDeclaredMethods()), Arrays.stream(theClass.getMethods())) 28 | .anyMatch(IsBenchmarkMethod.INSTANCE); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/discovery/predicates/IsBenchmarkMethod.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.discovery.predicates; 11 | 12 | import java.lang.reflect.Method; 13 | import java.util.function.Predicate; 14 | 15 | import org.openjdk.jmh.annotations.Benchmark; 16 | 17 | /** 18 | * {@link Predicate} to check whether a {@link Method} is a {@code @Benchmark} method. 19 | * 20 | * @see IsBenchmarkClass 21 | */ 22 | public enum IsBenchmarkMethod implements Predicate { 23 | 24 | INSTANCE; 25 | 26 | @Override 27 | public boolean test(Method theMethod) { 28 | return theMethod.isAnnotationPresent(Benchmark.class); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/execution/ConditionEvaluator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.execution; 11 | 12 | import static java.lang.String.*; 13 | 14 | import org.junit.jupiter.api.extension.ConditionEvaluationResult; 15 | import org.junit.jupiter.api.extension.ExecutionCondition; 16 | import org.junit.jupiter.api.extension.ExtensionContext; 17 | import org.junit.jupiter.engine.extension.ExtensionRegistry; 18 | import org.junit.platform.commons.logging.Logger; 19 | import org.junit.platform.commons.logging.LoggerFactory; 20 | import org.junit.platform.commons.util.StringUtils; 21 | 22 | /** 23 | * Evaluates conditions for a benchmark class/benchmark method. 24 | */ 25 | class ConditionEvaluator { 26 | 27 | private static final Logger logger = LoggerFactory.getLogger(ConditionEvaluator.class); 28 | 29 | private static final ConditionEvaluationResult ENABLED = ConditionEvaluationResult.enabled( 30 | "No 'disabled' conditions encountered"); 31 | 32 | /** 33 | * Evaluate all {@link ExecutionCondition} extensions registered for the 34 | * supplied {@link ExtensionContext}. 35 | * 36 | * @param extensionRegistry the current {@link ExtensionRegistry} 37 | * @param context the current {@link ExtensionContext} 38 | * @return the first disabled {@link ConditionEvaluationResult}, or a default enabled {@link ConditionEvaluationResult} if no disabled conditions are encountered. 39 | */ 40 | ConditionEvaluationResult evaluate(ExtensionRegistry extensionRegistry, ExtensionContext context) { 41 | 42 | return extensionRegistry.stream(ExecutionCondition.class) 43 | .map(condition -> evaluate(condition, context)) 44 | .filter(ConditionEvaluationResult::isDisabled) 45 | .findFirst() 46 | .orElse(ENABLED); 47 | } 48 | 49 | /** 50 | * Evaluate a single {@link ExecutionCondition} extension. 51 | * 52 | * @param condition the current {@link ExecutionCondition} 53 | * @param context the current {@link ExtensionContext} 54 | * @return 55 | */ 56 | private ConditionEvaluationResult evaluate(ExecutionCondition condition, ExtensionContext context) { 57 | try { 58 | ConditionEvaluationResult result = condition.evaluateExecutionCondition(context); 59 | logResult(condition.getClass(), result); 60 | return result; 61 | } catch (Exception ex) { 62 | throw evaluationException(condition.getClass(), ex); 63 | } 64 | } 65 | 66 | private void logResult(Class conditionType, ConditionEvaluationResult result) { 67 | logger.debug(() -> format("Evaluation of condition [%s] resulted in: %s", conditionType.getName(), result)); 68 | } 69 | 70 | private ConditionEvaluationException evaluationException(Class conditionType, Exception ex) { 71 | String cause = StringUtils.isNotBlank(ex.getMessage()) ? ": " + ex.getMessage() : ""; 72 | return new ConditionEvaluationException( 73 | String.format("Failed to evaluate condition [%s]%s", conditionType.getName(), cause), ex); 74 | } 75 | 76 | /** 77 | * Exception thrown on failures while evaluating an {@link ExecutionCondition}. 78 | */ 79 | static class ConditionEvaluationException extends RuntimeException { 80 | 81 | ConditionEvaluationException(String message, Throwable cause) { 82 | super(message, cause); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/execution/ConfigurationParameterBenchmarkConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2020 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * https://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.execution; 11 | 12 | import jmh.mbr.core.BenchmarkConfigProperties; 13 | import jmh.mbr.core.BenchmarkConfigProperties.ConfigProperty; 14 | import jmh.mbr.core.BenchmarkConfiguration; 15 | import jmh.mbr.core.Environment; 16 | 17 | import java.time.Duration; 18 | import java.util.Map; 19 | import java.util.Optional; 20 | import java.util.function.Function; 21 | 22 | import org.junit.jupiter.engine.config.JupiterConfiguration; 23 | import org.junit.platform.engine.ConfigurationParameters; 24 | 25 | /** 26 | * {@link BenchmarkConfiguration} obtained from {@link ConfigurationParameters}. 27 | */ 28 | class ConfigurationParameterBenchmarkConfiguration implements BenchmarkConfiguration { 29 | 30 | private final JupiterConfiguration configuration; 31 | 32 | public ConfigurationParameterBenchmarkConfiguration(JupiterConfiguration configuration) { 33 | this.configuration = configuration; 34 | } 35 | 36 | @Override 37 | public boolean isEnabled() { 38 | return getConfigParameterOrDefault(BenchmarkConfigProperties.ENABLED, Boolean::parseBoolean); 39 | } 40 | 41 | @Override 42 | public int getWarmupIterations() { 43 | return getConfigParameterOrDefault(BenchmarkConfigProperties.WARMUP_ITERATIONS, Integer::parseInt); 44 | } 45 | 46 | @Override 47 | public Duration getWarmupTime() { 48 | return getConfigParameterOrDefault(BenchmarkConfigProperties.WARMUP_TIME, it -> Duration 49 | .ofSeconds(Long.parseLong(it))); 50 | } 51 | 52 | @Override 53 | public Map asMap() { 54 | 55 | Map properties = Environment.jmhConfigProperties(); 56 | BenchmarkConfigProperties.iterator().forEachRemaining(it -> { 57 | 58 | Object value = getConfigParameterOrDefault((ConfigProperty) it, t -> t); 59 | if (value != null) { 60 | properties.put(it.propertyName(), value); 61 | } 62 | }); 63 | return properties; 64 | } 65 | 66 | @Override 67 | public int getWarmupBatchSize() { 68 | return getConfigParameterOrDefault(BenchmarkConfigProperties.WARMUP_BATCH_SIZE, Integer::parseInt); 69 | } 70 | 71 | @Override 72 | public String getWarmupMode() { 73 | return getConfigParameterOrDefault(BenchmarkConfigProperties.WARMUP_MODE, it -> it); 74 | } 75 | 76 | @Override 77 | public int getMeasurementIterations() { 78 | return getConfigParameterOrDefault(BenchmarkConfigProperties.MEASUREMENT_ITERATIONS, Integer::parseInt); 79 | } 80 | 81 | @Override 82 | public int getMeasurementBatchSize() { 83 | return getConfigParameterOrDefault(BenchmarkConfigProperties.MEASUREMENT_BATCH_SIZE, Integer::parseInt); 84 | } 85 | 86 | @Override 87 | public Duration getMeasurementTime() { 88 | return getConfigParameterOrDefault(BenchmarkConfigProperties.MEASUREMENT_TIME, it -> Duration 89 | .ofSeconds(Long.parseLong(it))); 90 | } 91 | 92 | @Override 93 | public String getMode() { 94 | return getConfigParameterOrDefault(BenchmarkConfigProperties.MODE, it -> it); 95 | } 96 | 97 | @Override 98 | public Duration getTimeout() { 99 | return getConfigParameterOrDefault(BenchmarkConfigProperties.TIMEOUT, it -> Duration 100 | .ofSeconds(Long.parseLong(it))); 101 | } 102 | 103 | @Override 104 | public int getForksCount() { 105 | return getConfigParameterOrDefault(BenchmarkConfigProperties.FORKS, Integer::parseInt); 106 | } 107 | 108 | @Override 109 | public String publishUri() { 110 | return getConfigParameterOrDefault(BenchmarkConfigProperties.PUBLISH_URI, it -> it); 111 | } 112 | 113 | private T getConfigParameterOrDefault(ConfigProperty property, Function mapFunction) { 114 | 115 | for (String propertyName : property.propertyNames()) { 116 | 117 | Optional configValue = configuration.getRawConfigurationParameter(propertyName, mapFunction); 118 | if (configValue.isPresent()) { 119 | return configValue.get(); 120 | } 121 | } 122 | 123 | return property.defaultValue(); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/java/jmh/mbr/junit5/execution/ExtensionContextProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.execution; 11 | 12 | import jmh.mbr.junit5.descriptor.AbstractBenchmarkDescriptor; 13 | import jmh.mbr.junit5.descriptor.BenchmarkClassDescriptor; 14 | 15 | import java.io.Closeable; 16 | import java.io.IOException; 17 | import java.util.LinkedHashMap; 18 | import java.util.Map; 19 | import java.util.Optional; 20 | 21 | import org.junit.jupiter.api.extension.ExtensionContext; 22 | import org.junit.jupiter.engine.config.JupiterConfiguration; 23 | import org.junit.platform.commons.logging.Logger; 24 | import org.junit.platform.commons.logging.LoggerFactory; 25 | import org.junit.platform.engine.EngineExecutionListener; 26 | import org.junit.platform.engine.TestDescriptor; 27 | 28 | /** 29 | * Provides {@link ExtensionContext} for a {@link BenchmarkClassDescriptor}. 30 | */ 31 | class ExtensionContextProvider implements AutoCloseable { 32 | 33 | private static final Logger logger = LoggerFactory.getLogger(ConditionEvaluator.class); 34 | 35 | private final EngineExecutionListener listener; 36 | private final JupiterConfiguration configuration; 37 | private final Map contextMap = new LinkedHashMap<>(); 38 | 39 | private ExtensionContextProvider(EngineExecutionListener listener, JupiterConfiguration configuration) { 40 | this.listener = listener; 41 | this.configuration = configuration; 42 | } 43 | 44 | /** 45 | * Creates a new {@link ExtensionContextProvider}. 46 | * 47 | * @param listener must not be {@literal null}. 48 | * @param configuration must not be {@literal null}. 49 | * @return the new {@link ExtensionContextProvider}. 50 | */ 51 | static ExtensionContextProvider create(EngineExecutionListener listener, JupiterConfiguration configuration) { 52 | return new ExtensionContextProvider(listener, configuration); 53 | } 54 | 55 | ExtensionContext getExtensionContext(Optional benchmarkClassDescriptor) { 56 | 57 | return benchmarkClassDescriptor.filter(BenchmarkClassDescriptor.class::isInstance) 58 | .map(BenchmarkClassDescriptor.class::cast) 59 | .map(this::getExtensionContext) 60 | .orElse(null); 61 | } 62 | 63 | ExtensionContext getExtensionContext(BenchmarkClassDescriptor descriptor) { 64 | return contextMap.computeIfAbsent(descriptor, key -> key.getExtensionContext(null, listener, configuration)); 65 | } 66 | 67 | @Override 68 | public void close() { 69 | 70 | contextMap.values() 71 | .stream() 72 | .filter(Closeable.class::isInstance) 73 | .map(Closeable.class::cast) 74 | .forEach(closeable -> { 75 | try { 76 | closeable.close(); 77 | } catch (IOException e) { 78 | logger.error(e, () -> String.format("Cannot close context [%s]", closeable)); 79 | } 80 | }); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/main/resources/META-INF/services/org.junit.platform.engine.TestEngine: -------------------------------------------------------------------------------- 1 | jmh.mbr.junit5.MicrobenchmarkEngine 2 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/test/java/jmh/mbr/junit5/JmhSupportStub.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package jmh.mbr.junit5; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | import jmh.mbr.core.BenchmarkConfiguration; 22 | import jmh.mbr.core.JmhSupport; 23 | import jmh.mbr.core.model.BenchmarkResults; 24 | import org.openjdk.jmh.runner.format.OutputFormat; 25 | 26 | /** 27 | * Stub for {@link jmh.mbr.junit5.execution.JmhRunner} that collects results into {@link List} additional to publication. 28 | */ 29 | public class JmhSupportStub extends JmhSupport { 30 | 31 | final List resultsList = new ArrayList<>(); 32 | final BenchmarkConfiguration initOptions; 33 | 34 | public JmhSupportStub(BenchmarkConfiguration jmhOptions) { 35 | 36 | super(jmhOptions); 37 | this.initOptions = jmhOptions; 38 | } 39 | 40 | @Override 41 | public void publishResults(OutputFormat output, BenchmarkResults results) { 42 | 43 | this.resultsList.add(results); 44 | super.publishResults(output, results); 45 | } 46 | 47 | public BenchmarkResults getBenchmarkResults() { 48 | 49 | if (resultsList.isEmpty()) { 50 | return null; 51 | } 52 | 53 | return resultsList.get(resultsList.size() - 1); 54 | } 55 | 56 | public BenchmarkConfiguration getInitOptions() { 57 | return initOptions; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/test/java/jmh/mbr/junit5/ParametrizedBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5; 11 | 12 | import org.junit.jupiter.api.Tag; 13 | import org.openjdk.jmh.annotations.Benchmark; 14 | import org.openjdk.jmh.annotations.Fork; 15 | import org.openjdk.jmh.annotations.Measurement; 16 | import org.openjdk.jmh.annotations.Param; 17 | import org.openjdk.jmh.annotations.Scope; 18 | import org.openjdk.jmh.annotations.State; 19 | import org.openjdk.jmh.annotations.Warmup; 20 | 21 | @Warmup(iterations = 1, time = 1) 22 | @Measurement(iterations = 1, time = 1) 23 | @Fork(value = 1, warmups = 1) 24 | @State(Scope.Benchmark) 25 | @Microbenchmark 26 | @Tag("foo") 27 | public class ParametrizedBenchmark { 28 | 29 | @Param({ "a", "b" }) String foo; 30 | 31 | @Benchmark 32 | public void foo() {} 33 | } 34 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/test/java/jmh/mbr/junit5/PartiallyParametrizedBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5; 11 | 12 | import org.junit.platform.commons.annotation.Testable; 13 | import org.openjdk.jmh.annotations.Benchmark; 14 | import org.openjdk.jmh.annotations.Fork; 15 | import org.openjdk.jmh.annotations.Measurement; 16 | import org.openjdk.jmh.annotations.Param; 17 | import org.openjdk.jmh.annotations.Scope; 18 | import org.openjdk.jmh.annotations.State; 19 | import org.openjdk.jmh.annotations.Warmup; 20 | 21 | @Warmup(iterations = 1, time = 1) 22 | @Measurement(iterations = 1, time = 1) 23 | @Fork(value = 1, warmups = 1) 24 | @Microbenchmark 25 | public class PartiallyParametrizedBenchmark { 26 | 27 | @State(Scope.Benchmark) 28 | public static class ParamState { 29 | @Param({ "a", "b" }) String foo; 30 | } 31 | 32 | @Benchmark 33 | public void foo() { 34 | 35 | } 36 | 37 | @Benchmark 38 | @Testable 39 | public void bar(ParamState paramState) {} 40 | } 41 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/test/java/jmh/mbr/junit5/descriptor/BenchmarkClassDescriptorUnitTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.descriptor; 11 | 12 | import static org.assertj.core.api.Assertions.*; 13 | 14 | import java.util.Collections; 15 | 16 | import jmh.mbr.core.model.BenchmarkClass; 17 | import jmh.mbr.junit5.ParametrizedBenchmark; 18 | import org.junit.jupiter.api.Test; 19 | import org.junit.platform.engine.UniqueId; 20 | import org.junit.platform.launcher.PostDiscoveryFilter; 21 | import org.junit.platform.launcher.TagFilter; 22 | 23 | /** 24 | * Unit tests for {@link BenchmarkClassDescriptor}. 25 | */ 26 | class BenchmarkClassDescriptorUnitTests { 27 | 28 | @Test 29 | void shouldApplyTagFilter() { 30 | 31 | PostDiscoveryFilter includeFoo = TagFilter.includeTags("foo"); 32 | PostDiscoveryFilter includeBar = TagFilter.includeTags("bar"); 33 | 34 | BenchmarkClass benchmarkClass = BenchmarkClass.create(ParametrizedBenchmark.class, Collections.emptyList()); 35 | BenchmarkClassDescriptor descriptor = new BenchmarkClassDescriptor(UniqueId.root("root", "root"), benchmarkClass); 36 | 37 | assertThat(includeFoo.apply(descriptor).included()).isTrue(); 38 | assertThat(includeBar.apply(descriptor).included()).isFalse(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/test/java/jmh/mbr/junit5/discovery/JavaElementsResolverUnitTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.discovery; 11 | 12 | import jmh.mbr.junit5.PartiallyParametrizedBenchmark; 13 | import jmh.mbr.junit5.descriptor.BenchmarkClassDescriptor; 14 | import jmh.mbr.junit5.descriptor.BenchmarkMethodDescriptor; 15 | import jmh.mbr.junit5.descriptor.ParametrizedBenchmarkMethodDescriptor; 16 | 17 | import static org.assertj.core.api.Assertions.*; 18 | import org.junit.jupiter.api.Test; 19 | import org.junit.platform.commons.support.scanning.ClassFilter; 20 | import org.junit.platform.engine.TestDescriptor; 21 | import org.junit.platform.engine.UniqueId; 22 | import org.junit.platform.engine.discovery.DiscoverySelectors; 23 | import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; 24 | 25 | /** 26 | * Unit tests for {@link JavaElementsResolver}. 27 | */ 28 | class JavaElementsResolverUnitTests { 29 | 30 | private final TestDescriptor ENGINE = new AbstractTestDescriptor(UniqueId.forEngine("foo"), "foo") { 31 | @Override 32 | public Type getType() { 33 | return Type.CONTAINER; 34 | } 35 | }; 36 | 37 | private final ClassFilter FILTER = ClassFilter.of(it -> true); 38 | 39 | @Test 40 | void shouldResolveClassByPackageSelector() { 41 | 42 | JavaElementsResolver resolver = new JavaElementsResolver(ENGINE, 43 | ClassFilter.of(it -> it.equals(PartiallyParametrizedBenchmark.class)), ElementResolvers.getResolvers()); 44 | 45 | resolver 46 | .resolvePackage(DiscoverySelectors.selectPackage(PartiallyParametrizedBenchmark.class.getPackage().getName())); 47 | 48 | assertThat(ENGINE.getChildren()).hasSize(1); 49 | 50 | TestDescriptor classDescriptor = ENGINE.getChildren().iterator().next(); 51 | 52 | assertBenchmarkClass(classDescriptor); 53 | 54 | assertThat(classDescriptor.getChildren()).hasSize(2).hasOnlyElementsOfTypes(BenchmarkMethodDescriptor.class, 55 | ParametrizedBenchmarkMethodDescriptor.class); 56 | 57 | assertParametrizedMethod(classDescriptor); 58 | } 59 | 60 | @Test 61 | void shouldResolveClassByClassSelector() { 62 | 63 | JavaElementsResolver resolver = new JavaElementsResolver(ENGINE, FILTER, ElementResolvers.getResolvers()); 64 | 65 | resolver.resolveClass(DiscoverySelectors.selectClass(PartiallyParametrizedBenchmark.class)); 66 | 67 | assertThat(ENGINE.getChildren()).hasSize(1); 68 | 69 | TestDescriptor classDescriptor = ENGINE.getChildren().iterator().next(); 70 | 71 | assertBenchmarkClass(classDescriptor); 72 | 73 | assertThat(classDescriptor.getChildren()).hasSize(2).hasOnlyElementsOfTypes(BenchmarkMethodDescriptor.class, 74 | ParametrizedBenchmarkMethodDescriptor.class); 75 | 76 | assertParametrizedMethod(classDescriptor); 77 | } 78 | 79 | @Test 80 | void shouldResolveBenchmarkMethodByMethodSelector() { 81 | 82 | JavaElementsResolver resolver = new JavaElementsResolver(ENGINE, FILTER, ElementResolvers.getResolvers()); 83 | 84 | resolver.resolveMethod(DiscoverySelectors.selectMethod(PartiallyParametrizedBenchmark.class, "bar", 85 | "jmh.mbr.junit5.PartiallyParametrizedBenchmark$ParamState")); 86 | 87 | assertThat(ENGINE.getChildren()).hasSize(1); 88 | 89 | TestDescriptor classDescriptor = ENGINE.getChildren().iterator().next(); 90 | 91 | assertBenchmarkClass(classDescriptor); 92 | 93 | assertThat(classDescriptor.getChildren()).hasSize(1) 94 | .hasOnlyElementsOfTypes(ParametrizedBenchmarkMethodDescriptor.class); 95 | 96 | assertParametrizedMethod(classDescriptor); 97 | } 98 | 99 | @Test 100 | void shouldResolveBenchmarkMethodByUniqueIdSelector() { 101 | 102 | JavaElementsResolver resolver = new JavaElementsResolver(ENGINE, FILTER, ElementResolvers.getResolvers()); 103 | 104 | resolver.resolveUniqueId(DiscoverySelectors.selectUniqueId( 105 | "[engine:microbenchmark-engine]/[class:jmh.mbr.junit5.PartiallyParametrizedBenchmark]/[method:bar(jmh.mbr.junit5.PartiallyParametrizedBenchmark$ParamState)]/[fixture:%5Bfoo=b%5D]")); 106 | 107 | assertThat(ENGINE.getChildren()).hasSize(1); 108 | 109 | TestDescriptor classDescriptor = ENGINE.getChildren().iterator().next(); 110 | 111 | assertBenchmarkClass(classDescriptor); 112 | 113 | assertThat(classDescriptor.getChildren()).hasSize(1) 114 | .hasOnlyElementsOfTypes(ParametrizedBenchmarkMethodDescriptor.class); 115 | 116 | TestDescriptor parametrizedDescriptor = classDescriptor.getChildren().stream() 117 | .filter(ParametrizedBenchmarkMethodDescriptor.class::isInstance).findFirst().get(); 118 | 119 | assertThat(parametrizedDescriptor.getChildren()).hasSize(1); 120 | } 121 | 122 | private void assertBenchmarkClass(TestDescriptor classDescriptor) { 123 | assertThat(classDescriptor).isInstanceOf(BenchmarkClassDescriptor.class); 124 | assertThat(classDescriptor.getSource()).isNotEmpty(); 125 | assertThat(classDescriptor.getDisplayName()).isEqualTo(PartiallyParametrizedBenchmark.class.getName()); 126 | } 127 | 128 | private void assertParametrizedMethod(TestDescriptor classDescriptor) { 129 | 130 | TestDescriptor parametrizedDescriptor = classDescriptor.getChildren().stream() 131 | .filter(ParametrizedBenchmarkMethodDescriptor.class::isInstance).findFirst().get(); 132 | 133 | assertThat(parametrizedDescriptor.getChildren()).hasSize(2); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/test/java/jmh/mbr/junit5/discovery/predicates/IsBenchmarkClassUnitTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.discovery.predicates; 11 | 12 | import static org.assertj.core.api.Assertions.*; 13 | 14 | import java.util.function.Predicate; 15 | 16 | import org.junit.jupiter.api.Test; 17 | import org.openjdk.jmh.annotations.Benchmark; 18 | 19 | /** 20 | * Unit tests for {@link IsBenchmarkClass}. 21 | */ 22 | public class IsBenchmarkClassUnitTests { 23 | 24 | @Test 25 | void shouldDiscoverBenchmark() { 26 | 27 | assertThat((Predicate>) IsBenchmarkClass.INSTANCE).accepts(WithBenchmark.class); 28 | assertThat((Predicate>) IsBenchmarkClass.INSTANCE).rejects(NoBenchmark.class); 29 | } 30 | 31 | static class NoBenchmark {} 32 | 33 | public static class WithBenchmark { 34 | 35 | @Benchmark 36 | public void benchmarkMethod() { 37 | 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /microbenchmark-runner-junit5/src/test/java/jmh/mbr/junit5/execution/ConditionEvaluatorUnitTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * All rights reserved. This program and the accompanying materials are 5 | * made available under the terms of the Eclipse Public License v2.0 which 6 | * accompanies this distribution and is available at 7 | * 8 | * http://www.eclipse.org/legal/epl-v20.html 9 | */ 10 | package jmh.mbr.junit5.execution; 11 | 12 | import jmh.mbr.core.model.BenchmarkClass; 13 | import jmh.mbr.junit5.descriptor.BenchmarkClassDescriptor; 14 | import jmh.mbr.junit5.execution.JmhRunnerUnitTests.EmptyOutputDirectoryProvider; 15 | 16 | import java.util.Collections; 17 | import java.util.Optional; 18 | import java.util.Set; 19 | 20 | import static org.assertj.core.api.Assertions.*; 21 | import org.junit.jupiter.api.Disabled; 22 | import org.junit.jupiter.api.Test; 23 | import org.junit.jupiter.api.extension.ConditionEvaluationResult; 24 | import org.junit.jupiter.api.extension.ExecutionCondition; 25 | import org.junit.jupiter.api.extension.ExtendWith; 26 | import org.junit.jupiter.api.extension.ExtensionContext; 27 | import org.junit.jupiter.engine.config.DefaultJupiterConfiguration; 28 | import org.junit.jupiter.engine.config.JupiterConfiguration; 29 | import org.junit.jupiter.engine.extension.ExtensionRegistry; 30 | import org.junit.jupiter.engine.extension.MutableExtensionRegistry; 31 | import org.junit.platform.engine.ConfigurationParameters; 32 | import org.junit.platform.engine.UniqueId; 33 | import org.openjdk.jmh.annotations.Benchmark; 34 | 35 | /** 36 | * Unit tests for {@link ConditionEvaluator}. 37 | */ 38 | public class ConditionEvaluatorUnitTests { 39 | 40 | JupiterConfiguration configuration = new DefaultJupiterConfiguration(JmhRunnerUnitTests.EmptyConfigurationParameters.INSTANCE, EmptyOutputDirectoryProvider.INSTANCE); 41 | 42 | @Test 43 | void shouldRunWithoutCondition() { 44 | 45 | ExtensionRegistry registry = MutableExtensionRegistry 46 | .createRegistryWithDefaultExtensions(configuration); 47 | 48 | BenchmarkClassDescriptor descriptor = createDescriptor(SimpleBenchmarkClass.class); 49 | 50 | ConditionEvaluator evaluator = new ConditionEvaluator(); 51 | ConditionEvaluationResult result = evaluator.evaluate(registry, descriptor 52 | .getExtensionContext(null, null, configuration)); 53 | 54 | assertThat(result.isDisabled()).isFalse(); 55 | } 56 | 57 | @Test 58 | void shouldSkipDisabledBenchmarkClass() { 59 | 60 | ExtensionRegistry registry = MutableExtensionRegistry 61 | .createRegistryWithDefaultExtensions(configuration); 62 | 63 | BenchmarkClassDescriptor descriptor = createDescriptor(DisabledBenchmark.class); 64 | 65 | ConditionEvaluator evaluator = new ConditionEvaluator(); 66 | ConditionEvaluationResult result = evaluator.evaluate(registry, descriptor 67 | .getExtensionContext(null, null, configuration)); 68 | 69 | assertThat(result.isDisabled()).isTrue(); 70 | } 71 | 72 | @Test 73 | void shouldSkipDisabledThroughExtensionClass() { 74 | 75 | MutableExtensionRegistry parentRegistry = MutableExtensionRegistry 76 | .createRegistryWithDefaultExtensions(configuration); 77 | 78 | BenchmarkClassDescriptor descriptor = createDescriptor(CustomExtensionBenchmark.class); 79 | ExtensionRegistry registry = descriptor.getExtensionRegistry(parentRegistry); 80 | 81 | ConditionEvaluator evaluator = new ConditionEvaluator(); 82 | ConditionEvaluationResult result = evaluator.evaluate(registry, descriptor 83 | .getExtensionContext(null, null, configuration)); 84 | 85 | assertThat(result.isDisabled()).isTrue(); 86 | assertThat(result.getReason()).contains("always disabled"); 87 | } 88 | 89 | private BenchmarkClassDescriptor createDescriptor(Class javaClass) { 90 | BenchmarkClass benchmarkClass = BenchmarkClass 91 | .create(javaClass, Collections.emptyList()); 92 | return new BenchmarkClassDescriptor(UniqueId 93 | .root("root", "root"), benchmarkClass); 94 | } 95 | 96 | 97 | public static class SimpleBenchmarkClass { 98 | 99 | @Benchmark 100 | public void justOne() { 101 | } 102 | } 103 | 104 | @Disabled 105 | public static class DisabledBenchmark { 106 | 107 | @Benchmark 108 | public void justOne() { 109 | } 110 | } 111 | 112 | @ExtendWith(NeverRunExtension.class) 113 | public static class CustomExtensionBenchmark { 114 | 115 | @Benchmark 116 | public void justOne() { 117 | } 118 | } 119 | 120 | enum EmptyConfigurationParameters implements ConfigurationParameters { 121 | INSTANCE; 122 | 123 | @Override 124 | public Optional get(String key) { 125 | return Optional.empty(); 126 | } 127 | 128 | @Override 129 | public Optional getBoolean(String key) { 130 | return Optional.empty(); 131 | } 132 | 133 | 134 | @Override 135 | public int size() { 136 | return 0; 137 | } 138 | 139 | @Override 140 | public Set keySet() { 141 | return Collections.emptySet(); 142 | } 143 | } 144 | 145 | static class NeverRunExtension implements ExecutionCondition { 146 | 147 | @Override 148 | public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { 149 | return ConditionEvaluationResult.disabled("always disabled"); 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" 124 | FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( 125 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 126 | ) 127 | 128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 130 | if exist %WRAPPER_JAR% ( 131 | echo Found %WRAPPER_JAR% 132 | ) else ( 133 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 134 | echo Downloading from: %DOWNLOAD_URL% 135 | powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" 136 | echo Finished downloading %WRAPPER_JAR% 137 | ) 138 | @REM End of extension 139 | 140 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 141 | if ERRORLEVEL 1 goto error 142 | goto end 143 | 144 | :error 145 | set ERROR_CODE=1 146 | 147 | :end 148 | @endlocal & set ERROR_CODE=%ERROR_CODE% 149 | 150 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 151 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 152 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 153 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 154 | :skipRcPost 155 | 156 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 157 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 158 | 159 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 160 | 161 | exit /B %ERROR_CODE% 162 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | org.sonatype.oss 9 | oss-parent 10 | 9 11 | 12 | 13 | com.github.mp911de.microbenchmark-runner 14 | microbenchmark-runner-parent 15 | 0.6.0.BUILD-SNAPSHOT 16 | pom 17 | JUnit-based Microbenchmark Runners for JMH 18 | 19 | 20 | microbenchmark-runner-core 21 | microbenchmark-runner-extras 22 | microbenchmark-runner-junit4 23 | microbenchmark-runner-junit5 24 | microbenchmark-runner-junit5-smoke-tests 25 | 26 | 27 | 28 | 1.37 29 | 3.21.0 30 | 4.13.1 31 | 5.12.2 32 | 33 | 34 | http://github.com/mp911de/microbenchmark-runner 35 | 36 | 37 | 38 | Eclipse Public License - v 2.0 39 | http://www.eclipse.org/legal/epl-v20.html 40 | repo 41 | 42 | 43 | 44 | 45 | GitHub Actions 46 | https://github.com/mp911de/microbenchmark-runner/actions 47 | 48 | 49 | 50 | Github 51 | https://github.com/mp911de/microbenchmark-runner/issues 52 | 53 | 54 | 55 | scm:git:https://github.com/mp911de/microbenchmark-runner.git 56 | scm:git:https://github.com/mp911de/microbenchmark-runner.git 57 | http://github.com/mp911de/microbenchmark-runner 58 | HEAD 59 | 60 | 61 | 62 | 63 | 64 | org.openjdk.jmh 65 | jmh-core 66 | ${jmh.version} 67 | 68 | 69 | 70 | org.openjdk.jmh 71 | jmh-generator-annprocess 72 | ${jmh.version} 73 | provided 74 | 75 | 76 | 77 | org.junit 78 | junit-bom 79 | ${junit5.version} 80 | pom 81 | import 82 | 83 | 84 | 85 | junit 86 | junit 87 | ${junit4.version} 88 | 89 | 90 | 91 | org.assertj 92 | assertj-core 93 | ${assertj.version} 94 | test 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | maven-javadoc-plugin 103 | 3.11.2 104 | 105 | 106 | javadoc 107 | 108 | jar 109 | 110 | package 111 | 112 | 113 | 114 | none 115 | 8 116 | 117 | 118 | 119 | maven-source-plugin 120 | 3.3.1 121 | 122 | 123 | attach-sources 124 | 125 | jar 126 | 127 | package 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | org.apache.maven.plugins 137 | maven-compiler-plugin 138 | 3.14.0 139 | 140 | 1.8 141 | 1.8 142 | 143 | 144 | 145 | 146 | org.apache.maven.plugins 147 | maven-surefire-plugin 148 | 3.5.3 149 | 150 | 151 | **/*Tests 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /src/main/resources/start-benchmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mp911de/microbenchmark-runner/233b7b3293bd1bca8e9dd4189883befb1bfebf99/src/main/resources/start-benchmark.png --------------------------------------------------------------------------------