Hi all,

I spend a lot of time recently on trying to improve indy and well, the current architecture makes it difficult to solve problems. Right now I am stuck in a test that uses an in groovy written AST transform that fails under certain conditions to fire the right exception... So I am thinking of throwing away most of the branch. But there are some take-aways that I will probably put into a new pull request.

* DefaultTypeTransformation can have some fastpaths by simply reducing the method size by handling the common case and fall back to a new method for more complex cases * dgm helpers are strictly seen not needed in Indy actually. But I can also not easily remove them from the build. I think static groovy compiles directly against them. But what I will do is store a MethodHandle in them, that I will then use in Indy, instead * the cache in IndyInterface is in my eyes more a megamorphic cache. I experimented with an alternate key mechanism, I think I will also keep that.

None of these change will make indy dramatically faster. The DTT change will actually benefit everything that uses DTT.

There is more, more difficult things.

One is checking the metaclass for a change. So in the old callsite logic if I change the metaclass of X then a callsite on Y is not affected by it. If we change the ExpandoMetaClass, it will also not change the callsite with Y as receiver. In indy we use the switchpoint logic, which invalidates all callsites. That worked for getting things done, but is too much for code that makes rapid changes to meta classes. So I am considering giving up on the switchpoint and instead do a check similar to what the old callsite caching does with checking for an identical metaclass and its version. Or I start with the switchpoint, try to recognize if there are too many changes and fall back to the old logic. The switchpoint is cheap as check.

Another point is when we have to catch a GroovyRuntimeException to unwrap it, because the GroovyRuntimeException is in some cases used to control the MOP. That is what got me stuck on my branch, so it will try again in a clean and isolated approach

I also tried to make a small inline cache where the fallback will just forward to an older handle for the callsite to allow 3-4 changes to the callsite before it needs different treatment. I may try this again in the future, since I think this may help. I also tried in there to have only one switchpoint for the whole PIC, but as I said, the switchpoint is relatively fast. Having only one exception unwrap in there would probably have better results. The less checks the handle have to perform individually the better.

But frankly for this kind of information we would have to collect something like a profile, which I consider doing, but that could result in changing IndyInterface and Selector a lot. There is small gains, like moving some information about the callsite, that is not changing on the actual callsite instead of carrying them around in bound handles. That looks small, but reduces method signatures.

in fact for the future I am considering having IndyInterface really only as a entry point for the profile and then let different profiles handle the details, including handing over to a different profile. No exact plans here yet. But I think that can allow us doing some complex and specialized strategies without loosing - it... really... the errors I had to deal with where driving me mad.

Then there was also the idea of a slow path, where we can avoid more checks and just invoke via meta class. I think here I will also have to try again. I think having a simple path for highly mutating callsites and also for the initial callsites might be of advantage.

Finally I think I have to add something that allows better debugging of Indy. Maybe something where I can register a set of origin classes and keep a structure for their callsites, that is accessible from a Groovy script. Then a test could test its callsite state without writing tests for invoking methods through IndyInterface. Not sure yet.

Will make any of this Grails faster? Maybe. The metaclass churn and the exception handling overhead are both hot candidates for performance improvements in a Grails environment.

Well, any thoughts and ideas are welcome

bye Jochen

Reply via email to