mirror of
https://gitlab.uni-marburg.de/langbeid/powersort.git
synced 2025-01-21 19:50:35 +01:00
benchmark: separate JMH benchmarks
This commit is contained in:
parent
1a356490e4
commit
648af1c4be
@ -6,7 +6,9 @@
|
|||||||
plugins {
|
plugins {
|
||||||
// Apply the application plugin to add support for building a CLI application in Java.
|
// Apply the application plugin to add support for building a CLI application in Java.
|
||||||
application
|
application
|
||||||
|
|
||||||
// JMH Gradle Plugin
|
// JMH Gradle Plugin
|
||||||
|
// https://github.com/melix/jmh-gradle-plugin/blob/master/README.adoc#usage
|
||||||
id("me.champeau.jmh") version "0.7.2"
|
id("me.champeau.jmh") version "0.7.2"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15,14 +17,17 @@ repositories {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val latestJmhVersion = "1.37"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// Use JUnit Jupiter for testing.
|
// Use JUnit Jupiter for testing.
|
||||||
testImplementation(libs.junit.jupiter)
|
testImplementation(libs.junit.jupiter)
|
||||||
|
|
||||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||||
|
|
||||||
// This dependency is used by the application.
|
// Required to use the IntelliJ plugin "JMH Java Microbenchmark Harness".
|
||||||
//implementation(libs.guava)
|
// https://stackoverflow.com/a/71286156/6334421
|
||||||
|
jmhAnnotationProcessor("org.openjdk.jmh:jmh-generator-annprocess:$latestJmhVersion")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply a specific Java toolchain to ease working on different environments.
|
// Apply a specific Java toolchain to ease working on different environments.
|
||||||
@ -57,4 +62,21 @@ tasks.named<Test>("test") {
|
|||||||
// HTML reports to view with a webbrowser.
|
// HTML reports to view with a webbrowser.
|
||||||
html.required.set(true)
|
html.required.set(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/melix/jmh-gradle-plugin/blob/master/README.adoc#configuration-options
|
||||||
|
jmh {
|
||||||
|
// Use latest JMH version (1.37, https://github.com/openjdk/jmh/tags)
|
||||||
|
// instead of default (1.36, https://github.com/melix/jmh-gradle-plugin/blob/dfdbb0cd3a363e2dbbcaab93bb1be32178f4cae4/src/main/java/me/champeau/jmh/DefaultsConfigurer.java#L24)
|
||||||
|
jmhVersion = latestJmhVersion // Specifies JMH version
|
||||||
|
|
||||||
|
// Force GC (garbage collection) between iterations.
|
||||||
|
//
|
||||||
|
// Forcing the GC may help to lower the noise in GC-heavy benchmarks, at the expense of jeopardizing GC ergonomics decisions. Use with care.
|
||||||
|
// https://github.com/openjdk/jmh/blob/1be779e0b4af174b67abf8080d1b76dda570d88d/jmh-core/src/main/java/org/openjdk/jmh/runner/options/CommandLineOptions.java#L148-L152
|
||||||
|
forceGC = true
|
||||||
|
|
||||||
|
excludes = listOf(
|
||||||
|
"de.uni_marburg.powersort.benchmark.JmhBase.benchmark",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -3,6 +3,7 @@ package de.uni_marburg.powersort.benchmark;
|
|||||||
import de.uni_marburg.powersort.data.DataEnum;
|
import de.uni_marburg.powersort.data.DataEnum;
|
||||||
import de.uni_marburg.powersort.data.ObjectSupplier;
|
import de.uni_marburg.powersort.data.ObjectSupplier;
|
||||||
import de.uni_marburg.powersort.sort.SortEnum;
|
import de.uni_marburg.powersort.sort.SortEnum;
|
||||||
|
import de.uni_marburg.powersort.sort.SortImpl;
|
||||||
import org.openjdk.jmh.annotations.Benchmark;
|
import org.openjdk.jmh.annotations.Benchmark;
|
||||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||||
import org.openjdk.jmh.annotations.Fork;
|
import org.openjdk.jmh.annotations.Fork;
|
||||||
@ -10,7 +11,6 @@ import org.openjdk.jmh.annotations.Level;
|
|||||||
import org.openjdk.jmh.annotations.Measurement;
|
import org.openjdk.jmh.annotations.Measurement;
|
||||||
import org.openjdk.jmh.annotations.Mode;
|
import org.openjdk.jmh.annotations.Mode;
|
||||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||||
import org.openjdk.jmh.annotations.Param;
|
|
||||||
import org.openjdk.jmh.annotations.Scope;
|
import org.openjdk.jmh.annotations.Scope;
|
||||||
import org.openjdk.jmh.annotations.Setup;
|
import org.openjdk.jmh.annotations.Setup;
|
||||||
import org.openjdk.jmh.annotations.State;
|
import org.openjdk.jmh.annotations.State;
|
||||||
@ -36,19 +36,24 @@ import java.util.concurrent.TimeUnit;
|
|||||||
* State objects naturally encapsulate the state on which benchmark is working on.
|
* State objects naturally encapsulate the state on which benchmark is working on.
|
||||||
*/
|
*/
|
||||||
@State(Scope.Benchmark)
|
@State(Scope.Benchmark)
|
||||||
public class MainJmh {
|
public class JmhBase {
|
||||||
@Param()
|
DataEnum getDataEnum(){
|
||||||
private DataEnum dataEnum;
|
return null;
|
||||||
@Param()
|
}
|
||||||
private SortEnum sortEnum;
|
SortEnum getSortEnum(){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private ObjectSupplier data = null;
|
private ObjectSupplier data = null;
|
||||||
/* package-protected */ Object[] workingCopy;
|
Object[] workingCopy;
|
||||||
|
SortImpl sortImpl;
|
||||||
|
|
||||||
// TODO: This is inaccurate. How to create and use separate arrays for each warmup x iteration x sortAlgorithm ?
|
// TODO: This is inaccurate. How to create and use separate arrays for each warmup x iteration x sortAlgorithm ?
|
||||||
@Setup(Level.Invocation)
|
@Setup(Level.Invocation)
|
||||||
public void setup() {
|
public void setup() {
|
||||||
if(Filter.isFiltered(dataEnum, sortEnum)) {
|
sortImpl = getSortEnum().getSortImpl();
|
||||||
|
|
||||||
|
if (Filter.isFiltered(getDataEnum(), getSortEnum())) {
|
||||||
// This combination of DataEnum and SortEnum should be skipped.
|
// This combination of DataEnum and SortEnum should be skipped.
|
||||||
// We can't tell JMH to not run the benchmark at all.
|
// We can't tell JMH to not run the benchmark at all.
|
||||||
// Instead, we let it sort an invalid list which results in an exception.
|
// Instead, we let it sort an invalid list which results in an exception.
|
||||||
@ -59,12 +64,12 @@ public class MainJmh {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A new MainJmh object is created for each @Param variation.
|
// A new JmhRunner object is created for each @Param variation.
|
||||||
// Then, `data` is `null` again.
|
// Then, `data` is `null` again.
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
data = dataEnum.getObjectSupplier();
|
data = getDataEnum().getObjectSupplier();
|
||||||
}
|
}
|
||||||
// For all warmup and measurement iterations of one @Param variation, the MainJmh object is reused.
|
// For all warmup and measurement iterations of one @Param variation, the JmhRunner object is reused.
|
||||||
// Thus, we can't just sort `data` directly.
|
// Thus, we can't just sort `data` directly.
|
||||||
// Instead, we have to create a copy of it on which the sort algorithm can work.
|
// Instead, we have to create a copy of it on which the sort algorithm can work.
|
||||||
// This way, all iterations sort the same input.
|
// This way, all iterations sort the same input.
|
||||||
@ -73,6 +78,6 @@ public class MainJmh {
|
|||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
public void benchmark() {
|
public void benchmark() {
|
||||||
sortEnum.getSortImpl().sort(workingCopy);
|
sortImpl.sort(workingCopy);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package de.uni_marburg.powersort.benchmark;
|
||||||
|
|
||||||
|
import de.uni_marburg.powersort.data.DataEnum;
|
||||||
|
import de.uni_marburg.powersort.sort.SortEnum;
|
||||||
|
import org.openjdk.jmh.annotations.Param;
|
||||||
|
import org.openjdk.jmh.annotations.Scope;
|
||||||
|
import org.openjdk.jmh.annotations.State;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Benchmark state parameters
|
||||||
|
*
|
||||||
|
* Quote from JMH:
|
||||||
|
* State objects naturally encapsulate the state on which benchmark is working on.
|
||||||
|
*/
|
||||||
|
@State(Scope.Benchmark)
|
||||||
|
public class JmhCompetition extends JmhBase {
|
||||||
|
@Param()
|
||||||
|
DataEnum dataEnum;
|
||||||
|
@Param()
|
||||||
|
SortEnum sortEnum;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
DataEnum getDataEnum(){
|
||||||
|
return dataEnum;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
SortEnum getSortEnum(){
|
||||||
|
return sortEnum;
|
||||||
|
}
|
||||||
|
}
|
@ -1,14 +0,0 @@
|
|||||||
package de.uni_marburg.powersort.benchmark;
|
|
||||||
|
|
||||||
public abstract class SortImpl {
|
|
||||||
final String title;
|
|
||||||
|
|
||||||
public SortImpl(String title) {
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply the sort algorithm.
|
|
||||||
*/
|
|
||||||
public abstract void sort(Object[] a);
|
|
||||||
}
|
|
@ -3,7 +3,7 @@ package de.uni_marburg.powersort.data;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public abstract class ObjectSupplier {
|
public abstract class ObjectSupplier {
|
||||||
/* package-protected */ final Object[] readOnly;
|
final Object[] readOnly;
|
||||||
|
|
||||||
ObjectSupplier(Object[] readOnly) {
|
ObjectSupplier(Object[] readOnly) {
|
||||||
this.readOnly = readOnly;
|
this.readOnly = readOnly;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user