danielsun1106 edited a comment on issue #1135: GROOVY-8298: Slow Performance Caused by Invoke Dynamic URL: https://github.com/apache/groovy/pull/1135#issuecomment-570811643 Jochen, the main idea can be described as the following simplified code: ```java if (cacheHits(receiverCassName)) { // Try to find the cached MethodHandle // the main logic of `fromCache` MethodHandle mh = lruCache.get(receiverCassName); // find the cached MethodHandle again... return mh.invokeExact(...); } else { // fallback, and put the fallback methodhandle to the inline cache(LRU) for reuse // the main logic of `selectMethod` Selector selector = Selector.getSelector(...); selector.setCallSiteTarget(); MethodHandle mh = selector.handle.asSpreader(...).asType(MethodType.methodType(Object.class, Object[].class)); lruCache.put(receiverCassName, mh); // cache the methodhandle return mh.invokeExact(...); } ``` As the inline cache is implemented as LRU cache, and `cacheHits` and `fromCache` are executed in two steps(not atomic), so if `cacheHits` returns `true`(means cached methodhandle found), `fromCache` find the same cached methodhandle from LRU cache again, the result probably is `null` as cached methodhandle may be cleared according to the rule of LRU... I use `ThreadLocal` to avoid the above concurrent issue. Also, we have the inline cache for callsite, so `setTarget` can be avoided, which causes the poor performance as the GROOVY-8298 shown. >a call x.foo(y) may add a handle X#foo(Y1) in the cache, but if y changes to Y2 your cache will still return X#foo(Y1), even though y may not be an instance of Y1. You will have to check the argument types. We cache the methodhandle with method type `MethodType.methodType(Object.class, Object[].class)`, so we will not encounter the issue, the following code runs well ;-) ```groovy def same(String obj) { return obj } def same(int obj) { return obj } def same(float obj) { return obj } for (int i = 0; i < 100000; i++) { [1, 1.0f, '1.0'].each { same(it) } } ``` (before tuning: 9s, after tuning: 6s, on my machine) ```groovy for (int i = 0; i < 100000; i++) { [1, 1.0f, '1.0'].each { it.toString() } } ``` (before tuning: 6s, after tuning: 2s, on my machine) More strict performance tests will be done with JMH, I have no idea how to enable indy for performance tests for now...
---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org With regards, Apache Git Services