A page has been added to our benchmark results reports showing the results possible when using the "fat-free" form:
https://apache.github.io/groovy/dev/bench/jmh-adhoc/ Cheers, Paul. On Mon, Jun 1, 2026 at 8:32 PM Paul King <[email protected]> wrote: > > 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. > >
