Skip to content

Commit da2bba6

Browse files
authored
Overhaul benchmarking infrastructure (#63)
Significantly reduces the overhead of benchmarking and provides more reliable real-world numbers
1 parent 76ff4ca commit da2bba6

29 files changed

+1617
-743
lines changed

build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ plugins {
55
id 'java-library'
66
id 'maven-publish'
77
id 'com.github.ben-manes.versions' version '0.50.0'
8-
id 'org.gradlex.extra-java-module-info' version '1.4.2'
8+
id 'org.gradlex.extra-java-module-info' version '1.8'
99
id 'net.minecraftforge.gradleutils' version '2.3.3'
1010
id 'net.minecraftforge.licenser' version '1.0.1'
1111
}
@@ -16,7 +16,7 @@ print("Version: $version")
1616

1717
java {
1818
toolchain.languageVersion = JavaLanguageVersion.of(16)
19-
modularity.inferModulePath.set(true)
19+
modularity.inferModulePath = true
2020
withSourcesJar()
2121
}
2222

@@ -101,4 +101,4 @@ allprojects {
101101
// Tests are expensive to run all variants, so only run if asked to
102102
if (!project.hasProperty('bulk_tests'))
103103
ext.VALID_VMS = ['Adoptium': [17]]//, 18, 19, 20, 21] ]
104-
}
104+
}

buildSrc/src/main/groovy/AggregateJmh.groovy

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ abstract class AggregateJmh extends DefaultTask {
3838

3939
int javaCount = 0
4040
for (def file : this.inputs.files) {
41-
if (file.equals(pastFile))
41+
if (file == pastFile)
4242
continue
4343
def (javaName,javaVersion) = file.name.substring('jmh-'.length(), file.name.length() - 5).split('-')
4444

@@ -61,8 +61,8 @@ abstract class AggregateJmh extends DefaultTask {
6161
}
6262
}
6363

64-
def onlyOneSuite = results.keySet().size() == 1 && results.values().iterator().next().keySet().size() == 1
65-
def loadOld = collate.isPresent() && collate.get()
64+
boolean onlyOneSuite = results.keySet().size() == 1 && results.values().iterator().next().keySet().size() == 1
65+
boolean loadOld = collate.isPresent() && collate.get()
6666

6767
def markdown,csv = 'Something went fucky'
6868
if (javaCount == 1) {
@@ -85,7 +85,7 @@ abstract class AggregateJmh extends DefaultTask {
8585
outputCsv.asFile.get().text = csv
8686
}
8787

88-
static def rsplit(def str, def del, int limit = -1) {
88+
static def rsplit(def str, String del, int limit = -1) {
8989
def lst = []
9090
def x = 0, idx
9191
def tmp = str
@@ -97,7 +97,7 @@ abstract class AggregateJmh extends DefaultTask {
9797
return lst
9898
}
9999

100-
static def mergePast(def to, def from) {
100+
static void mergePast(def to, def from) {
101101
def pkg = to.keySet().iterator().next()
102102
if (!from.containsKey(pkg))
103103
return
@@ -135,7 +135,7 @@ abstract class AggregateJmh extends DefaultTask {
135135
*
136136
* This allows for comparison between multiple environments and implementations
137137
*/
138-
static def formatCollated(def results, def resultsPast, def timeUnit) {
138+
static def formatCollated(def results, def resultsPast, String timeUnit) {
139139
def columns = [' ']
140140
def rows = []
141141
def base = [:]
@@ -213,7 +213,7 @@ abstract class AggregateJmh extends DefaultTask {
213213
return markdown
214214
}
215215

216-
static def buildCsv(def columns, def rows, def headers = true, def prefix = '') {
216+
static String buildCsv(def columns, def rows, boolean headers = true, String prefix = '') {
217217
columns = [] + columns
218218
rows = [] + rows
219219
for (int x = 0; x < rows.size(); x++)
@@ -226,7 +226,7 @@ abstract class AggregateJmh extends DefaultTask {
226226
x--
227227
}
228228
}
229-
def csv = ''
229+
String csv = ''
230230
if (headers)
231231
csv += columns.join('\t') + '\n'
232232
for (def row : rows)
@@ -252,9 +252,9 @@ abstract class AggregateJmh extends DefaultTask {
252252
* | postStaticHundred | 5878.851 | 5325.055 | -9% |
253253
* Relative - Percentage change vs first suite
254254
*/
255-
static def formatBulk(def results, def resultsPast, def timeUnit, def javas, def versions) {
256-
def markdown = ''
257-
def onlyOneSuite = results.keySet().size() == 1 && results.values().iterator().next().keySet().size() == 1
255+
static def formatBulk(def results, def resultsPast, String timeUnit, def javas, def versions) {
256+
String markdown = ''
257+
boolean onlyOneSuite = results.keySet().size() == 1 && results.values().iterator().next().keySet().size() == 1
258258
def columns = [' ']
259259
def csvTable = [:]
260260
versions.forEach { version -> columns += [version, 'Change', 'Relative'] }
@@ -330,7 +330,7 @@ abstract class AggregateJmh extends DefaultTask {
330330
}
331331
}
332332
}
333-
def csvData = ''
333+
String csvData = ''
334334
for (def line : csv)
335335
csvData += line.join('\t') + '\n'
336336

eventbus-jmh/build.gradle

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ dependencies {
2828
implementation(libs.securemodules)
2929
implementation(libs.modlauncher)
3030
implementation(libs.unsafe)
31-
implementation(project(':eventbus-test-jar'))
31+
implementation(projects.eventbusTestJar)
3232

33-
implementation('org.openjdk.jmh:jmh-core:1.37')
34-
runtimeOnly('org.openjdk.jmh:jmh-generator-annprocess:1.37')
35-
annotationProcessor('org.openjdk.jmh:jmh-generator-annprocess:1.37')
33+
implementation libs.jmh.core
34+
runtimeOnly libs.jmh.annotationProcessor
35+
annotationProcessor libs.jmh.annotationProcessor
3636
}
3737

3838
extraJavaModuleInfo {
@@ -57,15 +57,16 @@ tasks.register('archiveJfr', ArchiveJfr) {
5757
output = file('build/jmh_profile_results/archive/')
5858
}
5959

60-
tasks.register('jmh').configure {
61-
dependsOn('aggregateJmh', 'archiveJfr')
60+
tasks.register('jmh') {
61+
dependsOn 'aggregateJmh'
6262
}
6363

64-
VALID_VMS.each { javaVendor, javaVersions ->
65-
javaVersions.each { int javaVersion ->
66-
def output = file("build/jmh_results/jmh-${javaVendor}-${javaVersion}.json")
67-
def outputJfr = file("build/jmh_profile_results/last_run/${javaVendor}-${javaVersion}/")
68-
def task = tasks.register("jmh${javaVendor}${javaVersion}", JavaExec) {
64+
((Map<String, List<Integer>>) ext.VALID_VMS).forEach { javaVendor, javaVersions ->
65+
for (Integer javaVersion in javaVersions) {
66+
var output = file("build/jmh_results/jmh-${javaVendor}-${javaVersion}.json")
67+
var outputJfr = file("build/jmh_profile_results/last_run/${javaVendor}-${javaVersion}/")
68+
outputJfr.mkdirs()
69+
var task = tasks.register("jmh${javaVendor}${javaVersion}", JavaExec) {
6970
classpath = sourceSets.main.runtimeClasspath
7071
mainModule = 'net.minecraftforge.eventbus.jmh'
7172
mainClass = 'net.minecraftforge.eventbus.benchmarks.Main'
@@ -81,32 +82,44 @@ VALID_VMS.each { javaVendor, javaVersions ->
8182
'-tu', 'ns', // Time unit: [m, s, ms, us, ns]
8283
'-f', '1', // Forks per benchmark
8384
'-rf', 'json', // Results File Format
84-
'-prof', 'stack', // Profiler: Simple and naive Java stack profiler
85-
'-prof', "jfr:dir=${outputJfr}", // Profiler: Java Flight Recorder profiler
85+
86+
// Todo: Conditionally enable these when given a debug flag. Log a warning if they are enabled
87+
// saying that they should only be used for identifying hotspots and to not trust the
88+
// results of the benchmarks when they are enabled.
89+
// '-prof', 'stack', // Profiler: Simple and naive Java stack profiler
90+
// '-prof', "jfr:dir=${outputJfr}", // Profiler: Java Flight Recorder profiler
91+
92+
// Comment out the line below to enable BenchmarkClassLoader. This sets up a transformed environment
93+
// with ModLauncher but *doesn't* call useModLauncher() in BusBuilder.
94+
'-e', 'BenchmarkClassLoader.*',
95+
8696
'-v', 'EXTRA', // Verbosity [SILENT, NORMAL, EXTRA]
8797
'-foe', 'true', // Fail on error
8898
'-rff', output,
8999
]
90100
if (project.hasProperty('bench'))
91101
args += project.property('bench')
92-
102+
93103
doFirst {
94-
if (outputJfr.exists())
95-
outputJfr.deleteDir()
104+
outputJfr.deleteDir()
96105
if (!output.parentFile.exists())
97-
output.parentFile.mkdirs()
106+
output.parentFile.mkdirs()
98107
if (output.exists())
99108
output.delete()
100109
}
101-
javaLauncher.set(javaToolchains.launcherFor {
102-
it.vendor.set(JvmVendorSpec."${javaVendor.toUpperCase(Locale.ROOT)}" as JvmVendorSpec)
103-
it.languageVersion.set(JavaLanguageVersion.of(javaVersion))
104-
it.implementation.set(JvmImplementation.VENDOR_SPECIFIC)
105-
})
110+
javaLauncher = javaToolchains.launcherFor {
111+
vendor = JvmVendorSpec."${javaVendor.toUpperCase(Locale.ROOT)}" as JvmVendorSpec
112+
languageVersion = JavaLanguageVersion.of(javaVersion)
113+
implementation = JvmImplementation.VENDOR_SPECIFIC
114+
}
115+
}
116+
tasks.named('aggregateJmh') {
117+
dependsOn task
118+
inputs.file output
119+
}
120+
tasks.named('archiveJfr') {
121+
dependsOn task
122+
inputs.dir outputJfr
106123
}
107-
aggregateJmh.dependsOn(task)
108-
aggregateJmh.inputs.file(output)
109-
archiveJfr.dependsOn(task)
110-
archiveJfr.inputs.dir(outputJfr)
111124
}
112125
}

eventbus-jmh/src/main/java/net/minecraftforge/eventbus/benchmarks/BenchmarkBase.java

Lines changed: 0 additions & 184 deletions
This file was deleted.

0 commit comments

Comments
 (0)