I created 17 new overloads for "fat-free" variants that can hook up
with "curryWith" (GROOVY-12043).
And 4 of the "With" style but not using that suffix - all marked @Incubating.
This was all I had planned for Groovy 6.0.X at this stage. Feedback welcome.
We can always add more if feedback shows that our users opt for this
slightly different style for the performance gains it offers.

https://issues.apache.org/jira/browse/GROOVY-12054

There is also an optimization for CurriedClosure for the simple case
(1-arg) in GROOVY-12044.
I haven't tried to do further CurriedClosure optimisations at this stage.

Cheers, Paul.

On Sun, May 24, 2026 at 12:46 AM Jochen Theodorou <[email protected]> wrote:
>
> Hi Paul,
>
>
> I think we have to separate memory consumption and performance a bit
> here. Of course allocating in a loop costs performance compared to not
> allocating. Creating new objects is not exactly cheap on the JVM, so
> here the two touch  for this case.
>
> For example the case of performance cost for CurriedClosure. Yes, we
> rewrap the array and thus we create a ton of useless Objects. But do we
> really have to? I think not. Nothing except manpower, time and
> motivation stops us from collapsing CurriedClosures. This can partially
> happen at construction time, partially this can happen at the callsite
> itself. And interestingly, we probably could even save on some guards..
> Actually there is some space for optimization in general. But this does
> not solve the problem of if you create the CurriedClosure inside the hot
> loop. Then you still carry the cost of creating lots of CurriedClosure
> objects.
>
> Quite some time ago I was toying with the idea of having a special
> non-capturing Closure, that is incompatible with the capturing Closure.
> Why? then for example a builder can make it clear by signature that it
> will require a delegate, or something like findAll can make it clear,
> that there will be no use of delegation. Well, that was an idea, did not
> get very far with it. I feel there is quite a bit optimization potential
> here as well - similar to non capturing lambdas. But if you then go and
> pack everything in a Closure as it is today, it won't got far I think.
>
> Which is also why this works with lambdas in static compilation, but not
> in dynamic Groovy... unless we fundamentally change the way these things
> are done. For example in "words.findAll(String::startsWith, 'A')", we
> could in theory just have a reusable wrapper for a MethodHandle, even
> create the wrapper at the callsite only (and keep it there) to tailor it
> to what we require for the method we call it with... hmm... that is
> similar to what is done for lambdas I think... just not as dynamic.
>
> Then there is the aspect of "looks". findAll with 2 parameters looks a
> bit odd on first look. But maybe that is something getting used too?
>
> bye Jochen
>
> On 5/23/26 14:53, Paul King wrote:
> > Hi folks,
> >
> > Donald Raab of Eclipse Collections fame, did a recent blog post about
> > what that library has done for better performance:
> >
> > https://donraab.medium.com/fat-free-lambdas-in-java-bf228da0613b
> >
> > Donald sent me a private message asking about Groovy's take on some of
> > those optimisations, so I thought it might be interesting to analyse
> > things. Past optimisation work, and the recent work Daniel did on
> > optimizing non-capturing lambdas put Groovy on a good footing for some
> > metrics but for many of our DGM methods that take Closures, we have
> > ways (with varying degrees of impact) to make things more performant.
> >
> > I did a benchmark and the results are in:
> >
> > https://issues.apache.org/jira/browse/GROOVY-12034
> >
> > There is a PR but currently the PR is just the benchmark tests
> > themselves, not any code changes at present:
> >
> > https://github.com/apache/groovy/pull/2557
> >
> > I'd encourage folks to read that ticket, we have a few options we
> > might want to explore.
> >
> > TL;DR
> > * there are a few potential optimsations we might be able to apply for
> > existing code
> > * we might want to consider a curryWith method, kind of a lazy rcurry
> > * we might want to consider the equivalent of Eclipse Collections
> > "*With" method variants. Instead of "words.findAll{ it.startsWith('A')
> > }" we'd have a variant "words.findAll(String::startsWith, 'A')
> >
> > Anyway, I'll ponder things a bit more and make some follow-up
> > PRs/emails. The analysis suggests just creating the extra variants on
> > a handful of the most widely used DGM methods. But feedback is most
> > welcome.
> >
> > Cheers, Paul.
>

Reply via email to