DATACMNS-637 - Performance improvements.

Made ObjectInstantiator interface public as otherwise the generated class to implement it cannot access it and thus the usage of the ByteCodeGeneratingEntityInstantiator fails completely.

PreferredConstructor.isEnclosingClassParameter(…) now eagerly returns if the parameter itself is not an enclosing one and thus avoids a collection lookup and equals check. Moved equals check for the type to the very end of the equals check to increase the chances that other inequality guards kick in earlier.

AbstractMappingContext now leaves the non-null-check for getPersistentEntity(…) to the factory method of ClassTypeInformation.

We now pre-calculate the hash codes for TypeInformation implementations as far as possible as the instances are used as cache keys quite a lot. The same applies to AbstractPersistentProperty.

BasicPersistentEntity now uses an ArrayList we sort during the verify() phase to mimic the previous behavior wich was implemented using a TreeSet as ArrayLists are way more performant when iterating over all elements which doWithProperties(…) is doing which is used quite a lot.

BeanWrapper now avoids the getter lookup if field access is used.

SimpleTypeHolder now uses a CopyOnWriteArrySet to leniently add types detected to be simple to the set of simple types to avoid ongoing checks against the inheritance hierarchy.
This commit is contained in:
Oliver Gierke
2015-01-24 13:22:14 +01:00
parent 5cc4811c52
commit df9f8c417e
12 changed files with 205 additions and 65 deletions

View File

@@ -0,0 +1,107 @@
/*
* Copyright 2014-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.util;
/**
* Wrapper to safely store {@literal null} values in the value cache.
*
* @author Patryk Wasik
* @author Oliver Gierke
* @author Thomas Darimont
*/
public class CacheValue<T> {
private static final CacheValue<?> ABSENT = new CacheValue<Object>(null);
private final T value;
/**
* Creates a new {@link CacheValue} for the gven value.
*
* @param type can be {@literal null}.
*/
private CacheValue(T type) {
this.value = type;
}
/**
* Returns the actual underlying value.
*
* @return
*/
public T getValue() {
return value;
}
/**
* Returns whether the cached value has an actual value.
*
* @return
*/
public boolean isPresent() {
return value != null;
}
/**
* Returns whether the cached value has the given actual value.
*
* @param value can be {@literal null};
* @return
*/
public boolean hasValue(T value) {
return isPresent() ? this.value.equals(value) : value == null;
}
/**
* Returns a new {@link CacheValue} for the given value.
*
* @param value can be {@literal null}.
* @return will never be {@literal null}.
*/
@SuppressWarnings("unchecked")
public static <T> CacheValue<T> ofNullable(T value) {
return value == null ? (CacheValue<T>) ABSENT : new CacheValue<T>(value);
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return isPresent() ? 0 : value.hashCode();
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof CacheValue)) {
return false;
}
CacheValue<?> that = (CacheValue<?>) obj;
return this.value == null ? false : this.value.equals(that.value);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2014 the original author or authors.
* Copyright 2011-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,8 +20,6 @@ import java.lang.reflect.TypeVariable;
import java.util.HashMap;
import java.util.Map;
import org.springframework.util.ObjectUtils;
/**
* Base class for {@link TypeInformation} implementations that need parent type awareness.
*
@@ -30,6 +28,7 @@ import org.springframework.util.ObjectUtils;
public abstract class ParentTypeAwareTypeInformation<S> extends TypeDiscoverer<S> {
private final TypeDiscoverer<?> parent;
private int hashCode;
/**
* Creates a new {@link ParentTypeAwareTypeInformation}.
@@ -99,6 +98,11 @@ public abstract class ParentTypeAwareTypeInformation<S> extends TypeDiscoverer<S
*/
@Override
public int hashCode() {
return super.hashCode() + 31 * ObjectUtils.nullSafeHashCode(parent);
if (this.hashCode == 0) {
this.hashCode = super.hashCode() + 31 * parent.hashCode();
}
return this.hashCode;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2014 the original author or authors.
* Copyright 2011-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,6 @@
*/
package org.springframework.data.util;
import static org.springframework.util.ObjectUtils.*;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
@@ -50,6 +48,7 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
private final Type type;
private final Map<TypeVariable<?>, Type> typeVariableMap;
private final Map<String, TypeInformation<?>> fieldTypes = new ConcurrentHashMap<String, TypeInformation<?>>();
private final int hashCode;
private boolean componentTypeResolved = false;
private TypeInformation<?> componentType;
@@ -72,6 +71,7 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
this.type = type;
this.typeVariableMap = typeVariableMap;
this.hashCode = 17 + (31 * type.hashCode()) + (31 * typeVariableMap.hashCode());
}
/**
@@ -513,10 +513,7 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
TypeDiscoverer<?> that = (TypeDiscoverer<?>) obj;
boolean typeEqual = nullSafeEquals(this.type, that.type);
boolean typeVariableMapEqual = nullSafeEquals(this.typeVariableMap, that.typeVariableMap);
return typeEqual && typeVariableMapEqual;
return this.type.equals(that.type) && this.typeVariableMap.equals(that.typeVariableMap);
}
/*
@@ -525,12 +522,6 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
*/
@Override
public int hashCode() {
int result = 17;
result += nullSafeHashCode(type);
result += nullSafeHashCode(typeVariableMap);
return result;
return hashCode;
}
}