Browse Source

DATACMNS-332 - Further performance improvements.

Reverted from ConcurrentHashMap to plain HashMap where concurrency wasn't an issue and profiling showed performance hotspots. Introduced caches for ParameterizedTypeInformation.getComponentType() and the resolved raw type in TypeDiscoverer.
1.5.x
Oliver Gierke 13 years ago
parent
commit
8eb6030fc0
  1. 16
      src/main/java/org/springframework/data/mapping/PreferredConstructor.java
  2. 4
      src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java
  3. 8
      src/main/java/org/springframework/data/util/ParameterizedTypeInformation.java
  4. 9
      src/main/java/org/springframework/data/util/TypeDiscoverer.java
  5. 5
      src/test/java/org/springframework/data/mapping/model/AbstractAnnotationBasedPropertyUnitTests.java

16
src/main/java/org/springframework/data/mapping/PreferredConstructor.java

@ -20,9 +20,9 @@ import static org.springframework.util.ObjectUtils.*;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.annotation.PersistenceConstructor; import org.springframework.data.annotation.PersistenceConstructor;
@ -41,13 +41,13 @@ public class PreferredConstructor<T, P extends PersistentProperty<P>> {
private final Constructor<T> constructor; private final Constructor<T> constructor;
private final List<Parameter<Object, P>> parameters; private final List<Parameter<Object, P>> parameters;
private final Map<PersistentProperty<?>, Boolean> isPropertyParameterCache = new ConcurrentHashMap<PersistentProperty<?>, Boolean>(); private final Map<PersistentProperty<?>, Boolean> isPropertyParameterCache = new HashMap<PersistentProperty<?>, Boolean>();
/** /**
* Creates a new {@link PreferredConstructor} from the given {@link Constructor} and {@link Parameter}s. * Creates a new {@link PreferredConstructor} from the given {@link Constructor} and {@link Parameter}s.
* *
* @param constructor * @param constructor must not be {@literal null}.
* @param parameters * @param parameters must not be {@literal null}.
*/ */
public PreferredConstructor(Constructor<T> constructor, Parameter<Object, P>... parameters) { public PreferredConstructor(Constructor<T> constructor, Parameter<Object, P>... parameters) {
@ -167,6 +167,7 @@ public class PreferredConstructor<T, P extends PersistentProperty<P>> {
private final PersistentEntity<T, P> entity; private final PersistentEntity<T, P> entity;
private Boolean enclosingClassCache; private Boolean enclosingClassCache;
private Boolean hasSpelExpression;
/** /**
* Creates a new {@link Parameter} with the given name, {@link TypeInformation} as well as an array of * Creates a new {@link Parameter} with the given name, {@link TypeInformation} as well as an array of
@ -240,7 +241,12 @@ public class PreferredConstructor<T, P extends PersistentProperty<P>> {
* @return * @return
*/ */
public boolean hasSpelExpression() { public boolean hasSpelExpression() {
return StringUtils.hasText(getSpelExpression());
if (this.hasSpelExpression == null) {
this.hasSpelExpression = StringUtils.hasText(getSpelExpression());
}
return this.hasSpelExpression;
} }
/** /**

4
src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java

@ -29,8 +29,6 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
@ -68,7 +66,7 @@ import org.springframework.util.ReflectionUtils.FieldFilter;
public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?, P>, P extends PersistentProperty<P>> public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?, P>, P extends PersistentProperty<P>>
implements MappingContext<E, P>, ApplicationEventPublisherAware, InitializingBean, ApplicationContextAware { implements MappingContext<E, P>, ApplicationEventPublisherAware, InitializingBean, ApplicationContextAware {
private final ConcurrentMap<TypeInformation<?>, E> persistentEntities = new ConcurrentHashMap<TypeInformation<?>, E>(); private final Map<TypeInformation<?>, E> persistentEntities = new HashMap<TypeInformation<?>, E>();
private ApplicationEventPublisher applicationEventPublisher; private ApplicationEventPublisher applicationEventPublisher;

8
src/main/java/org/springframework/data/util/ParameterizedTypeInformation.java

@ -35,6 +35,7 @@ import org.springframework.core.GenericTypeResolver;
class ParameterizedTypeInformation<T> extends ParentTypeAwareTypeInformation<T> { class ParameterizedTypeInformation<T> extends ParentTypeAwareTypeInformation<T> {
private final ParameterizedType type; private final ParameterizedType type;
private TypeInformation<?> componentType;
/** /**
* Creates a new {@link ParameterizedTypeInformation} for the given {@link Type} and parent {@link TypeDiscoverer}. * Creates a new {@link ParameterizedTypeInformation} for the given {@link Type} and parent {@link TypeDiscoverer}.
@ -136,7 +137,12 @@ class ParameterizedTypeInformation<T> extends ParentTypeAwareTypeInformation<T>
*/ */
@Override @Override
public TypeInformation<?> getComponentType() { public TypeInformation<?> getComponentType() {
return createInfo(type.getActualTypeArguments()[0]);
if (componentType == null) {
this.componentType = createInfo(type.getActualTypeArguments()[0]);
}
return this.componentType;
} }
/* /*

9
src/main/java/org/springframework/data/util/TypeDiscoverer.java

@ -51,6 +51,8 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
private final Map<TypeVariable, Type> typeVariableMap; private final Map<TypeVariable, Type> typeVariableMap;
private final Map<String, TypeInformation<?>> fieldTypes = new ConcurrentHashMap<String, TypeInformation<?>>(); private final Map<String, TypeInformation<?>> fieldTypes = new ConcurrentHashMap<String, TypeInformation<?>>();
private Class<S> resolvedType;
/** /**
* Creates a ne {@link TypeDiscoverer} for the given type, type variable map and parent. * Creates a ne {@link TypeDiscoverer} for the given type, type variable map and parent.
* *
@ -261,7 +263,12 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
* @see org.springframework.data.util.TypeInformation#getType() * @see org.springframework.data.util.TypeInformation#getType()
*/ */
public Class<S> getType() { public Class<S> getType() {
return resolveType(type);
if (resolvedType == null) {
this.resolvedType = resolveType(type);
}
return this.resolvedType;
} }
/* /*

5
src/test/java/org/springframework/data/mapping/model/AbstractAnnotationBasedPropertyUnitTests.java

@ -24,7 +24,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -108,8 +107,8 @@ public class AbstractAnnotationBasedPropertyUnitTests<P extends AnnotationBasedP
context.getPersistentEntity(InvalidSample.class); context.getPersistentEntity(InvalidSample.class);
fail("Expected MappingException!"); fail("Expected MappingException!");
} catch (MappingException o_O) { } catch (MappingException o_O) {
ConcurrentMap<TypeInformation<?>, ?> entities = (ConcurrentMap<TypeInformation<?>, ?>) ReflectionTestUtils Map<TypeInformation<?>, ?> entities = (Map<TypeInformation<?>, ?>) ReflectionTestUtils.getField(context,
.getField(context, "persistentEntities"); "persistentEntities");
assertThat(entities.containsKey(ClassTypeInformation.from(InvalidSample.class)), is(false)); assertThat(entities.containsKey(ClassTypeInformation.from(InvalidSample.class)), is(false));
} }
} }

Loading…
Cancel
Save