You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2018/05/25 01:15:42 UTC

groovy git commit: GROOVY-8604: Cache the parameterized type for better performance(closes #721)

Repository: groovy
Updated Branches:
  refs/heads/master 90486ae10 -> ed71b35e7


GROOVY-8604: Cache the parameterized type for better performance(closes #721)


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/ed71b35e
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/ed71b35e
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/ed71b35e

Branch: refs/heads/master
Commit: ed71b35e755090b1ae841e0e9888c0f61386d050
Parents: 90486ae
Author: sunlan <su...@apache.org>
Authored: Fri May 25 09:15:21 2018 +0800
Committer: sunlan <su...@apache.org>
Committed: Fri May 25 09:15:21 2018 +0800

----------------------------------------------------------------------
 .../groovy/ast/tools/GenericsUtils.java         | 65 ++++++++++++++++++--
 .../stc/StaticTypeCheckingSupport.java          |  2 +-
 .../stc/StaticTypeCheckingVisitor.java          |  2 +-
 3 files changed, 62 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/ed71b35e/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
index 2e8a103..3d99e53 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
@@ -36,6 +36,8 @@ import org.codehaus.groovy.ast.stmt.EmptyStatement;
 import org.codehaus.groovy.control.CompilationUnit;
 import org.codehaus.groovy.control.ResolveVisitor;
 import org.codehaus.groovy.control.SourceUnit;
+import org.codehaus.groovy.runtime.memoize.EvictableCache;
+import org.codehaus.groovy.runtime.memoize.StampedCommonCache;
 import org.codehaus.groovy.syntax.ParserException;
 import org.codehaus.groovy.syntax.Reduction;
 
@@ -46,6 +48,7 @@ import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicReference;
 
 import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.getCorrectedClassNode;
@@ -658,13 +661,22 @@ public class GenericsUtils {
     }
 
     /**
-     * Get the parameterized type by search the whole class hierarchy according to generics class and actual receiver
+     * Try to get the parameterized type from the cache.
+     * If no cached item found, cache and return the result of {@link #findParameterizedType(ClassNode, ClassNode)}
+     */
+    public static ClassNode findParameterizedTypeFromCache(final ClassNode genericsClass, final ClassNode actualType) {
+        return PARAMETERIZED_TYPE_CACHE.getAndPut(new ParameterizedTypeCacheKey(genericsClass, actualType), key -> findParameterizedType(key.getGenericsClass(), key.getActualType()));
+    }
+
+    /**
+     * Get the parameterized type by search the whole class hierarchy according to generics class and actual receiver.
+     * {@link #findParameterizedTypeFromCache(ClassNode, ClassNode)} is strongly recommended for better performance.
      *
      * @param genericsClass the generics class
-     * @param actualReceiver the actual receiver
+     * @param actualType the actual type
      * @return the parameterized type
      */
-    public static ClassNode findParameterizedType(ClassNode genericsClass, ClassNode actualReceiver) {
+    public static ClassNode findParameterizedType(ClassNode genericsClass, ClassNode actualType) {
         ClassNode parameterizedType = null;
 
         if (null == genericsClass.getGenericsTypes()) {
@@ -673,8 +685,8 @@ public class GenericsUtils {
 
         GenericsType[] declaringGenericsTypes = genericsClass.getGenericsTypes();
 
-        List<ClassNode> classNodeList = new LinkedList<>(getAllSuperClassesAndInterfaces(actualReceiver));
-        classNodeList.add(0, actualReceiver);
+        List<ClassNode> classNodeList = new LinkedList<>(getAllSuperClassesAndInterfaces(actualType));
+        classNodeList.add(0, actualType);
 
         for (ClassNode cn : classNodeList) {
             if (cn == genericsClass) {
@@ -720,4 +732,47 @@ public class GenericsUtils {
 
         return superClassNodeList;
     }
+
+    private static final EvictableCache<ParameterizedTypeCacheKey, ClassNode> PARAMETERIZED_TYPE_CACHE = new StampedCommonCache<>(128);
+    private static class ParameterizedTypeCacheKey {
+        private ClassNode genericsClass;
+        private ClassNode actualType;
+
+        public ParameterizedTypeCacheKey(ClassNode genericsClass, ClassNode actualType) {
+            this.genericsClass = genericsClass;
+            this.actualType = actualType;
+        }
+
+        public ClassNode getGenericsClass() {
+            return genericsClass;
+        }
+
+        public void setGenericsClass(ClassNode genericsClass) {
+            this.genericsClass = genericsClass;
+        }
+
+        public ClassNode getActualType() {
+            return actualType;
+        }
+
+        public void setActualType(ClassNode actualType) {
+            this.actualType = actualType;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            ParameterizedTypeCacheKey cacheKey = (ParameterizedTypeCacheKey) o;
+
+            return genericsClass == cacheKey.genericsClass &&
+                    actualType == cacheKey.actualType;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(genericsClass, actualType);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/groovy/blob/ed71b35e/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index 316953b..cf92a6e 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -1196,7 +1196,7 @@ public abstract class StaticTypeCheckingSupport {
     }
 
     private static Parameter[] makeRawTypes(Parameter[] params, ClassNode declaringClassForDistance, ClassNode actualReceiverForDistance) {
-        Map<String, GenericsType> placeholderInfo = GenericsUtils.extractPlaceholders(GenericsUtils.findParameterizedType(declaringClassForDistance, actualReceiverForDistance));
+        Map<String, GenericsType> placeholderInfo = GenericsUtils.extractPlaceholders(GenericsUtils.findParameterizedTypeFromCache(declaringClassForDistance, actualReceiverForDistance));
 
         Parameter[] newParam = new Parameter[params.length];
         for (int i = 0; i < params.length; i++) {

http://git-wip-us.apache.org/repos/asf/groovy/blob/ed71b35e/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index efa7c26..9a13abe 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -620,7 +620,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 }
             }
 
-            ClassNode parameterizedType = GenericsUtils.findParameterizedType(fieldNode.getDeclaringClass(), typeCheckingContext.getEnclosingClassNode());
+            ClassNode parameterizedType = GenericsUtils.findParameterizedTypeFromCache(fieldNode.getDeclaringClass(), typeCheckingContext.getEnclosingClassNode());
             if (null != parameterizedType) {
                 ClassNode originalType = fieldNode.getOriginType();
                 ClassNode actualType = findActualTypeByPlaceholderName(originalType.getUnresolvedName(), GenericsUtils.extractPlaceholders(parameterizedType));