Re: Looming Groovy 5 INDY-only Performance Problem
Jonny <[email protected]>
| Newsgroups | gmane.comp.lang.groovy.devel |
|---|---|
| Message-ID | <CANkfqQMO9gZx0nvtsO28Zr5j3EU6epxiWs2roP0OA2djfm7qPA@mail.gmail.com> |
Hey, James. I took that repository out for a spin today. I posted my findings at https://github.com/apache/grails-core/issues/15293#issuecomment-3712253386. In short, the profiler does indicate that most of the time is getting consumed in calls to java.lang.invoke.Invokers$Holder#linkToCallSite. That would suggest that there's not much low-hanging fruit to optimize away beyond addressing the problems with InvokeDynamic. It also renders me somewhat skeptical that switching to @CompileStatic would address the root problems in this case. Apologies that I don't have anything more useful to offer, but I figured I should at least share what I found. On Thu, Jan 1, 2026 at 1:22 AM James Daugherty <[email protected]> wrote: > Hi Jonny, > > I pinned this Grails ticket: > https://github.com/apache/grails-core/issues/15293 > > The user put together a benchmark repo with both a Grails 6 (groovy3) and > Grails 7 (groovy 4 with indy left enabled). We do not have a Groovy 5 > version working yet - there are still compile errors (as we have time we > have opened tickets to address and the groovy devs have been quick to fix > them). > > On a more personal note, I have a substantial Grails application in my > corporate job. While it uses most of the features of Grails, it also has a > large backend processing presence. This backend is more groovy than Grails > so performance impacts are very noticeable. I am happy to test or help > with any effort to make indy fast. The performance impacts are significant > enough that I too have had to disable indy when adopting Groovy 4. > > -James > > On Wed, Dec 31, 2025 at 4:39 PM Jonny <[email protected]> wrote: > >> I've only been on the edge of the discussion around performance on Groovy >> 4 & 5. Digging through some of the threads above has left me with a few >> thoughts. >> >> First, I would caution anyone who hopes that moving to plain Java is >> necessarily going to improve the problem of "major language upgrades >> sometimes require substantial rewrites." Java's got its own release train, >> and while they do play the conservative "last mover" advantage as much as >> they can, it's not like the problem of upgrades goes away. That said, it's >> worth considering whether we might be able to provide some help to folks >> upgrading to avoid common performance gotchas. I know there are OpenRewrite >> recipes for Gradle upgrades. If we knew where likely pitfalls were, maybe >> we could provide something similar for Groovy? We'd need to know what >> things to target, though, which brings me to a more specific, actionable >> point: >> >> In one case >> <https://lists.apache.org/thread/q257zbtvm0jgnr5gqojfcpphlfpoos94>, >> after the user switched from doing their performance testing in debug mode >> to a production mode (runWar), the performance gap closed significantly >> (about 200ms slower for rendering a large stress test page, rather than >> triple the time). I know that Jochen has some thoughts on improving the >> performance of InvokeDynamic, which probably could help address things in a >> "root cause" way. That said, Gianluca's experience makes me wonder if there >> are some other low-hanging fruit that would help address the problem for >> big Grails apps. I know that it was mentioned somewhere that someone >> provided a sample application that demonstrates some issues, but I haven't >> been able to find it on a second pass. Do you have that example app handy, >> mg? >> >> Best, >> >> Jonny >> >> >> On Wed, Dec 31, 2025 at 1:52 PM MG <mgbiz-yvYIh6MZAuFWk0Htik3J/[email protected]> wrote: >> >>> Hi .+, >>> >>> I just saw this 2 week old comment on Grails 7/Groovy 4 INDY performance >>> (bold by me; >>> https://github.com/apache/grails-core/issues/15293#issuecomment-3676632134 >>> ): >>> >>> Thanks for raising this issue, we also hit the problem of a massive >>> performance hit using Grails 7/Groovy 4 on our large codebase, and were >>> partially rectifying that by converting more of our code to either >>> @CompileStatic or just to Java. *Every Groovy upgrade has given us >>> challenges with compile performance, runtime performance, language >>> behaviour changes* etc *so our long term goal is to switch to pure Java* >>> which I believe will be more stable and perform better. The tip of >>> disabling indy has been very helpful because it's allowed us to get over >>> the issue for now and in fact due to the rework we've done, our app is >>> faster than before! >>> >>> >>> Even though in our large codebase we were able to successfully steer >>> around this issue by going partially @CompileStatic, I feel like Groovy 5 >>> being INDY-only could pose more of a risk for the future of the Groovy >>> language than previous changes, if more companies/orgs with larger Groovy >>> applications/frameworks decide to switch to Java. >>> >>> => >>> >>> 1. *To fix the root cause of performance drop-off:* *Could a Grails >>> application be used to try out the INDY performance improvements Jochen >>> suggested in August* ? >>> 1. (As I said before, our code needs to be closed source and we >>> therefore alas cannot supply the needed test case.) >>> 2. *To make switching to new Groovy major versions faster/easier >>> under @CompileStatic/@TypeChecked:* One of the main sources of >>> problems when doing the switch to a new major Groovy version we encounter, >>> is that Groovy continues to be *ever more strict with regards to >>> generics arguments*. >>> 1. A non-negligible part of the work to get the two base modules >>> of our framework to compile under @CompileStatic was adding "as >>> List<SomeClass>" or similar to our code, to get Groovy to accept it. >>> 2. I know covariance in general is a complicated & intricate >>> problem, but can we instead find a Groovy solution here following "make the >>> frequent case simple/fast, make the rare case correct", and instead of >>> being more strict*, do things like e.g. a List<ChildOfGoo> being >>> accepted as a List<Goo>* ? >>> 1. Some cases can of course be solved by using List<T extends >>> Goo>, but alas even this does not always work in more complex generics >>> constructs. >>> 1. (In some cases it would help to keep the code >>> Groovy-compact, if Groovy had its own more compact syntax for the List<? >>> extends Goo> variety, e.g. List<Goo*> (i.e. appending a "*" after the type) >>> ...) >>> >>> >>> A Groovy Happy New Year to everyone, Cheers, >>> mg >>> >>
Grails 6 hot path.png
(image/png, 260.5 KB) - not displayed
Grails 7 hot path.png
(image/png, 296.3 KB) - not displayed