You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2026/06/02 03:54:43 UTC
(groovy) 01/01: GROOVY-12034: Apply "fat-free lambda" patterns to Groovy (fix graphs and build warnings)
This is an automated email from the ASF dual-hosted git repository.
paulk-asert pushed a commit to branch fatFreeSpike
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 415e86e47d18579337ed3d02ca9122407992bfef
Author: Paul King <pa...@asert.com.au>
AuthorDate: Tue Jun 2 13:54:29 2026 +1000
GROOVY-12034: Apply "fat-free lambda" patterns to Groovy (fix graphs and build warnings)
---
.../main/groovy/org.apache.groovy-performance.gradle | 18 +++++++++++++++++-
.../performance/dashboard/jmh-adhoc-summary.html | 14 +++++++++++---
2 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/build-logic/src/main/groovy/org.apache.groovy-performance.gradle b/build-logic/src/main/groovy/org.apache.groovy-performance.gradle
index b57422bed4..1a9456b844 100644
--- a/build-logic/src/main/groovy/org.apache.groovy-performance.gradle
+++ b/build-logic/src/main/groovy/org.apache.groovy-performance.gradle
@@ -42,7 +42,12 @@ repositories {
}
dependencies {
- jmh project(':')
+ // Use jmhImplementation (not the bare `jmh` bucket): the jmh compile/runtime
+ // classpaths carry the full attribute set, so Gradle selects the shaded
+ // (jarjar) Groovy variant. The bare `jmh` configuration under-specifies
+ // attributes and falls back to the un-shaded *raw* variant, which put a second
+ // Groovy jar (plus duplicate asm/antlr) on the jmh classpath.
+ jmhImplementation project(':')
testImplementation project(':')
testImplementation "org.junit.jupiter:junit-jupiter-api:${versions.junit6}"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${versions.junit6}"
@@ -102,6 +107,17 @@ tasks.named('test') {
tasks.named('jmh') {
inputs.property('benchInclude', project.findProperty('benchInclude') ?: '')
dependsOn tasks.named('jmhClasses')
+ // me.champeau.jmh builds a self-contained uber jar (the jmhJar artifact) and
+ // then runs benchmarks with a classpath of: the `jmh` configuration + that
+ // uber jar + the test runtime classpath. That puts Groovy core on the run
+ // classpath three times — the `jmh` config even resolves the un-shaded *raw*
+ // Groovy variant (dragging duplicate asm/antlr) — which trips
+ // MetaClassRegistryImpl's "duplicate concurrent module" warning. The uber jar
+ // already contains everything needed to run, so clear the two loose
+ // collections and let it be the single source: every class (Groovy included)
+ // then appears exactly once.
+ jmhClasspath.setFrom()
+ testRuntimeClasspath.setFrom()
}
tasks.named('jmhJar') {
diff --git a/subprojects/performance/dashboard/jmh-adhoc-summary.html b/subprojects/performance/dashboard/jmh-adhoc-summary.html
index 912b7920eb..9e4e8065ba 100644
--- a/subprojects/performance/dashboard/jmh-adhoc-summary.html
+++ b/subprojects/performance/dashboard/jmh-adhoc-summary.html
@@ -134,10 +134,18 @@
// "findAllG_lambdasCurryWith (size=10000)" -> {family, variant, size}
// NB: findAll must precede find in the alternation so it wins the match.
+ // Two name shapes reach us, depending on which github-action-benchmark tool
+ // produced the series:
+ // alloc (customSmallerIsBetter): "findAllG_lambdasCurryWith (size=10000)"
+ // throughput (jmh tool): 'org.apache.groovy.adhoc.FatFreeLambdaBench.findAllG_lambdasCurryWith ( {"size":"10000"} )'
+ // Pull the method token (findAll/find/count + variant) and the size wherever
+ // they appear, instead of anchoring on one exact layout. NB: findAll must
+ // precede find in the alternation so it wins the match.
function parseName(name) {
- const m = name.match(/^(findAll|find|count)([^ ]+?)\s*\(size=(\d+)\)\s*$/);
- if (!m) return null;
- return { family: m[1], variant: m[2].replace(/^_/, ''), size: m[3] };
+ const fam = name.match(/(findAll|find|count)([A-Za-z0-9_]+)/);
+ const sz = name.match(/size["'\s:=]*?(\d+)/);
+ if (!fam || !sz) return null;
+ return { family: fam[1], variant: fam[2].replace(/^_/, ''), size: sz[1] };
}
// Shape a bench list into { variants:[...], bySize:{size:{variant:value}} } for one family.