From 4600190d016cc57a62873e2285af568d4c35eb1e Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 8 Aug 2018 11:49:27 +0200 Subject: [PATCH] DATACMNS-1366 - Performance improvements in mapping subsystem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We now use a presized HashMap and Weak references in BasicPersistentEntity to improve memory and CPU profile and and avoid unmodifiable collection creation in BasicPersistentEntity.iterator(). Refactored ClassTypeInformation.from(…) lambda to method reference and predefined collection size for the cache. Reduced object instantiations during TypeDiscoverer.equals(…) by checking for type variable map emptiness to avoid Map iterator creation in Map.equals(…). Original pull request: #305. --- .../mapping/model/BasicPersistentEntity.java | 18 ++++++++++++++++-- .../data/util/ClassTypeInformation.java | 7 ++++--- .../data/util/TypeDiscoverer.java | 10 +++++++++- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java b/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java index 511d52d58..2120232df 100644 --- a/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java +++ b/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java @@ -105,7 +105,7 @@ public class BasicPersistentEntity> implement this.constructor = PreferredConstructorDiscoverer.discover(this); this.associations = comparator == null ? new HashSet<>() : new TreeSet<>(new AssociationComparator<>(comparator)); - this.propertyCache = new HashMap<>(); + this.propertyCache = new HashMap<>(16, 1f); this.annotationCache = new ConcurrentReferenceHashMap<>(16, ReferenceType.WEAK); this.propertyAnnotationCache = CollectionUtils .toMultiValueMap(new ConcurrentReferenceHashMap<>(16, ReferenceType.WEAK)); @@ -507,7 +507,21 @@ public class BasicPersistentEntity> implement */ @Override public Iterator

iterator() { - return Collections.unmodifiableList(properties).iterator(); + + Iterator

iterator = properties.iterator(); + + return new Iterator

() { + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public P next() { + return iterator.next(); + } + }; } protected EvaluationContext getEvaluationContext(Object rootObject) { diff --git a/src/main/java/org/springframework/data/util/ClassTypeInformation.java b/src/main/java/org/springframework/data/util/ClassTypeInformation.java index bd1b1faea..637af2388 100644 --- a/src/main/java/org/springframework/data/util/ClassTypeInformation.java +++ b/src/main/java/org/springframework/data/util/ClassTypeInformation.java @@ -30,8 +30,8 @@ import java.util.Set; import org.springframework.core.GenericTypeResolver; import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; import org.springframework.util.ConcurrentReferenceHashMap; +import org.springframework.util.ConcurrentReferenceHashMap.ReferenceType; /** * {@link TypeInformation} for a plain {@link Class}. @@ -48,7 +48,8 @@ public class ClassTypeInformation extends TypeDiscoverer { public static final ClassTypeInformation MAP = new ClassTypeInformation(Map.class); public static final ClassTypeInformation OBJECT = new ClassTypeInformation(Object.class); - private static final Map, ClassTypeInformation> CACHE = new ConcurrentReferenceHashMap<>(); + private static final Map, ClassTypeInformation> CACHE = new ConcurrentReferenceHashMap<>(64, + ReferenceType.WEAK); static { Arrays.asList(COLLECTION, LIST, SET, MAP, OBJECT).forEach(it -> CACHE.put(it.getType(), it)); @@ -67,7 +68,7 @@ public class ClassTypeInformation extends TypeDiscoverer { Assert.notNull(type, "Type must not be null!"); - return (ClassTypeInformation) CACHE.computeIfAbsent(type, it -> new ClassTypeInformation<>(type)); + return (ClassTypeInformation) CACHE.computeIfAbsent(type, ClassTypeInformation::new); } /** diff --git a/src/main/java/org/springframework/data/util/TypeDiscoverer.java b/src/main/java/org/springframework/data/util/TypeDiscoverer.java index 59865c4b7..d3d19d362 100644 --- a/src/main/java/org/springframework/data/util/TypeDiscoverer.java +++ b/src/main/java/org/springframework/data/util/TypeDiscoverer.java @@ -549,7 +549,15 @@ class TypeDiscoverer implements TypeInformation { TypeDiscoverer that = (TypeDiscoverer) obj; - return this.type.equals(that.type) && this.typeVariableMap.equals(that.typeVariableMap); + if (!this.type.equals(that.type)) { + return false; + } + + if (this.typeVariableMap.isEmpty() && that.typeVariableMap.isEmpty()) { + return true; + } + + return this.typeVariableMap.equals(that.typeVariableMap); } /*