Skip to content

GROOVY-10307: backport JMH benchmarks from master to Groovy 4#2393

Open
jamesfredley wants to merge 1 commit intoapache:GROOVY_4_0_Xfrom
jamesfredley:groovy-10307-jmh-benchmarks-backport
Open

GROOVY-10307: backport JMH benchmarks from master to Groovy 4#2393
jamesfredley wants to merge 1 commit intoapache:GROOVY_4_0_Xfrom
jamesfredley:groovy-10307-jmh-benchmarks-backport

Conversation

@jamesfredley
Copy link
Contributor

Summary

Backport JMH benchmarks for invokedynamic performance patterns and Grails-like workload simulations from master to the GROOVY_4_0_X branch, enabling performance comparison testing on Groovy 4.

Changes

New JMH benchmarks (16 files)

Core Groovy performance (org.apache.groovy.perf):

  • ClosureBench - closure creation, reuse, capture, delegation, nesting, currying, composition, trampoline, collection operations
  • GStringBench - GString interpolation, concatenation, lazy evaluation
  • GroovyIdiomBench - Groovy idioms (safe navigation, elvis, spread, with/tap, destructuring)
  • LoopsBench - for/while/each/times/upto loop patterns
  • MetaclassBench - dynamic method dispatch overhead with metaclass changes
  • MethodInvocationBench - method dispatch (instance, static, overloaded, polymorphic, interface, dynamic)
  • OperatorBench - operator overloading, comparisons, range operations
  • PropertyAccessBench - property get/set patterns (direct, dynamic, nested)
  • RunnerRegistryBench - GroovyRunnerRegistry iterator performance

Grails-like patterns (org.apache.groovy.perf.grails):

  • CallSiteInvalidationBench - SwitchPoint invalidation overhead for cross-type and same-type metaclass changes
  • CategoryBench - category usage patterns (single, nested, simultaneous, shadowing)
  • DynamicDispatchBench - methodMissing, propertyMissing, invokeMethod, ExpandoMetaClass injection
  • GrailsLikePatternsBench - composite patterns (service chains, controller actions, domain validation, config DSL, markup builder, full request cycle)
  • GrailsWorkloadBench - collection closure chains, spread operator, nested closure delegation, GString interpolation, project metrics aggregation
  • MetaclassChangeBench - metaclass modification impact (expando additions, replacements, multi-class cascade, burst/steady-state, closure dispatch)
  • MetaclassVariationBench - per-instance ExpandoMetaClass overhead (GORM domain class enhancement pattern)

Build changes

  • Updated org.apache.groovy-performance.gradle to support indy property for toggling invokedynamic mode in JMH compilation (-Pindy=true|false, defaults to true)
  • Added jmh task input tracking and jmhJar output configuration

CI workflows

  • groovy-jmh.yml - runs JMH benchmarks with invokedynamic enabled (matrix: bench, core, grails suites)
  • groovy-jmh-classic.yml - runs JMH benchmarks with classic (non-indy) bytecode

Groovy 4 compatibility adaptation

  • DynamicDispatchBench: moved DynamicFinder, DynamicProperties, and MethodInterceptor from static inner classes to package-level classes because Groovy 4 does not support methodMissing/propertyMissing on static inner classes

Verification

  • Compiled successfully with ./gradlew :performance:jmhClasses (indy mode)
  • Compiled successfully with ./gradlew :performance:jmhClasses -Pindy=false (classic mode)

Backport JMH benchmarks for invokedynamic performance patterns and
Grails-like workload simulations from master to the GROOVY_4_0_X branch.

New benchmarks cover core Groovy performance (closures, GStrings, method
invocation, operators, property access, loops, metaclass overhead) and
Grails-specific patterns (call site invalidation, categories, dynamic
dispatch, metaclass changes, per-instance metaclass variation, workload
simulation, and composite request-cycle patterns).

Adapt DynamicDispatchBench for Groovy 4 compatibility: move classes
using methodMissing/propertyMissing to package level since Groovy 4
does not support these on static inner classes.

Update the performance gradle plugin to support indy/classic mode
selection for JMH compilation. Add CI workflows for running JMH
benchmarks in both indy and classic modes.
Copilot AI review requested due to automatic review settings March 5, 2026 12:44
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR backports a set of JMH microbenchmarks from master into the Groovy 4 branch to enable performance comparison testing, including Grails-like metaprogramming and invokedynamic invalidation scenarios, plus supporting build/CI wiring.

Changes:

  • Adds new JMH benchmark suites under org.apache.groovy.perf and org.apache.groovy.perf.grails covering closures, GStrings, operators, method/property dispatch, metaclass churn, categories, and workload simulations.
  • Updates performance Gradle build logic to allow toggling Groovy indy compilation via -Pindy=... and improves task input/output tracking.
  • Introduces CI workflows to run JMH in indy and “classic” (non-indy) modes across benchmark suites.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/grails/MetaclassVariationBench.groovy New benchmark for per-instance EMC overhead and cross-type churn scenarios.
subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/grails/MetaclassChangeBench.groovy New benchmark suite focusing on metaclass modification impact on indy call sites.
subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/grails/GrailsWorkloadBench.groovy New workload-style benchmarks based on Grails-like collection/DSL patterns.
subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/grails/GrailsLikePatternsBench.groovy Composite Grails-like request/service/domain/builder patterns.
subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/grails/DynamicDispatchBench.groovy Benchmarks for methodMissing/propertyMissing/invokeMethod/Expando injection dispatch.
subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/grails/CategoryBench.groovy Category usage benchmarks measuring invalidation overhead patterns.
subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/grails/CallSiteInvalidationBench.groovy Focused SwitchPoint invalidation benchmarks (same-/cross-type).
subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/RunnerRegistryBench.java New benchmark for GroovyRunnerRegistry iterator performance.
subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/PropertyAccessBench.groovy Property access microbenchmarks (fields/getters/maps/chaining).
subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/OperatorBench.groovy Operator dispatch microbenchmarks (arithmetic, subscripts, comparisons, etc.).
subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/MethodInvocationBench.groovy Method invocation microbenchmarks (overloads, polymorphism, def-typed).
subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/MetaclassBench.groovy Benchmarks for call dispatch under ongoing metaclass changes.
subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/LoopsBench.groovy Loop pattern benchmarks (each vs method call vs closure reuse, etc.).
subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/GroovyIdiomBench.groovy Groovy idiom benchmarks (safe nav, spread-dot, elvis, with/tap, ranges, as).
subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/GStringBench.groovy GString interpolation/concat/toString benchmarks.
subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/ClosureBench.groovy Closure creation/reuse/currying/composition/trampoline/collection operation benchmarks.
build-logic/src/main/groovy/org.apache.groovy-performance.gradle Adds -Pindy toggle and improves JMH task inputs/outputs.
.github/workflows/groovy-jmh.yml New CI workflow to run JMH suites with indy enabled.
.github/workflows/groovy-jmh-classic.yml New CI workflow to run JMH suites with indy disabled.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants