OPENJPA-141. A few improvements to the performance-related changes done with the previous Issue. Reference OPENJPA-141 for details. Biggest change was moving some of the common caching code to ImplHelper.

git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@508395 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Kevin W. Sutter 2007-02-16 13:52:08 +00:00
parent 7a2330ce3b
commit dfc102beba
5 changed files with 51 additions and 85 deletions

View File

@ -29,7 +29,7 @@ public class JNDIManagedRuntime
implements ManagedRuntime {
private String _tmLoc = "java:/TransactionManager";
private static TransactionManager _tm;
private TransactionManager _tm = null;
/**
* Return the location of the {@link TransactionManager} in JNDI.
@ -43,12 +43,14 @@ public class JNDIManagedRuntime
*/
public void setTransactionManagerName(String name) {
_tmLoc = name;
_tm = null; // reset the cached TM
}
/**
* Return the cached TransactionManager instance.
*/
public TransactionManager getTransactionManager() throws Exception {
if (_tm == null) {
Context ctx = new InitialContext();
try {

View File

@ -63,7 +63,6 @@ import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.ReferenceHashMap;
import org.apache.openjpa.lib.util.ReferenceHashSet;
import org.apache.openjpa.lib.util.ReferenceMap;
import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap;
import org.apache.openjpa.lib.util.concurrent.ReentrantLock;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
@ -75,6 +74,7 @@ import org.apache.openjpa.util.ApplicationIds;
import org.apache.openjpa.util.CallbackException;
import org.apache.openjpa.util.Exceptions;
import org.apache.openjpa.util.GeneralException;
import org.apache.openjpa.util.ImplHelper;
import org.apache.openjpa.util.InternalException;
import org.apache.openjpa.util.InvalidStateException;
import org.apache.openjpa.util.NoTransactionException;
@ -139,9 +139,6 @@ public class BrokerImpl
private static final Localizer _loc =
Localizer.forPackage(BrokerImpl.class);
// Cache for from/to type assignments
private static ConcurrentReferenceHashMap _assignableTypes =
new ConcurrentReferenceHashMap(ReferenceMap.HARD, ReferenceMap.WEAK);
// the store manager in use; this may be a decorator such as a
// data cache store manager around the native store manager
@ -1101,7 +1098,8 @@ public class BrokerImpl
cls));
return PCRegistry.newObjectId(cls, (String) val);
}
if (isAssignable(meta.getObjectIdType(), val.getClass())) {
if (ImplHelper.isAssignable(meta.getObjectIdType(), val.getClass()))
{
if (!meta.isOpenJPAIdentity() && meta.isObjectIdTypeShared())
return new ObjectId(cls, val);
return val;
@ -1122,37 +1120,6 @@ public class BrokerImpl
}
}
/**
* Cache from/to assignments to avoid Class.isAssignableFrom overhead
* @param from the target Class
* @param to the Class to test
* @return true if the "to" class could be assigned to "from" class
*/
private boolean isAssignable(Class from, Class to) {
boolean isAssignable;
ConcurrentReferenceHashMap assignableTo =
(ConcurrentReferenceHashMap) _assignableTypes.get(from);
if (assignableTo != null) { // "to" cache exists...
isAssignable = (assignableTo.get(to) != null);
if (!isAssignable) { // not in the map yet...
isAssignable = from.isAssignableFrom(to);
if (isAssignable) {
assignableTo.put(to, new Object());
}
}
} else { // no "to" cache yet...
isAssignable = from.isAssignableFrom(to);
if (isAssignable) {
assignableTo = new ConcurrentReferenceHashMap(
ReferenceMap.HARD, ReferenceMap.WEAK);
_assignableTypes.put(from, assignableTo);
assignableTo.put(to, new Object());
}
}
return isAssignable;
}
/**
* Create a new state manager for the given oid.
*/

View File

@ -36,11 +36,10 @@ import org.apache.openjpa.lib.rop.ResultObjectProvider;
import org.apache.openjpa.lib.rop.SimpleResultList;
import org.apache.openjpa.lib.rop.WindowResultList;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.ReferenceMap;
import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FetchGroup;
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.util.ImplHelper;
import org.apache.openjpa.util.InternalException;
import org.apache.openjpa.util.NoTransactionException;
import org.apache.openjpa.util.UserException;
@ -60,10 +59,6 @@ public class FetchConfigurationImpl
private static final Localizer _loc = Localizer.forPackage
(FetchConfigurationImpl.class);
// Cache the from/to isAssignable invocations
private static ConcurrentReferenceHashMap _assignableTypes =
new ConcurrentReferenceHashMap(ReferenceMap.HARD, ReferenceMap.WEAK);
/**
* Configurable state shared throughout a traversal chain.
*/
@ -563,7 +558,7 @@ public class FetchConfigurationImpl
// see if there's a previous limit
int avail = Integer.MIN_VALUE;
for (FetchConfigurationImpl f = this; f != null; f = f._parent) {
if (isAssignable(type, f._fromType)) {
if (ImplHelper.isAssignable(type, f._fromType)) {
avail = f._availableRecursion;
if (traverse)
avail = reduce(avail);
@ -588,15 +583,15 @@ public class FetchConfigurationImpl
max = cur;
}
// reduce max if we're traversing a self-type relation
if (traverse && max != Integer.MIN_VALUE
&& isAssignable(meta.getDescribedType(), type))
if (traverse && max != Integer.MIN_VALUE
&& ImplHelper.isAssignable(meta.getDescribedType(), type))
max = reduce(max);
// take min/defined of previous avail and fetch group max
if (avail == Integer.MIN_VALUE && max == Integer.MIN_VALUE) {
int def = FetchGroup.RECURSION_DEPTH_DEFAULT;
return (traverse && isAssignable(meta.getDescribedType(), type))
? def - 1 : def;
return (traverse && ImplHelper.isAssignable(
meta.getDescribedType(), type)) ? def - 1 : def;
}
if (avail == Integer.MIN_VALUE || avail == FetchGroup.DEPTH_INFINITE)
return max;
@ -618,40 +613,6 @@ public class FetchConfigurationImpl
return null;
}
/**
* Whether either of the two types is assignable from the other. Optimize
* for the repeat calls with similar parameters by caching the from/to
* type parameters.
*/
private static boolean isAssignable(Class from, Class to) {
boolean isAssignable;
if (from == null || to == null)
return false;
ConcurrentReferenceHashMap assignableTo =
(ConcurrentReferenceHashMap) _assignableTypes.get(from);
if (assignableTo != null) { // "to" cache exists...
isAssignable = (assignableTo.get(to) != null);
if (!isAssignable) { // not in the map yet...
isAssignable = from.isAssignableFrom(to);
if (isAssignable) {
assignableTo.put(to, new Object());
}
}
} else { // no "to" cache yet...
isAssignable = from.isAssignableFrom(to);
if (isAssignable) {
assignableTo = new ConcurrentReferenceHashMap(
ReferenceMap.HARD, ReferenceMap.WEAK);
_assignableTypes.put(from, assignableTo);
assignableTo.put(to, new Object());
}
}
return isAssignable;
}
/**
* Reduce the given logical depth by 1.
*/

View File

@ -20,8 +20,8 @@ import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.openjpa.enhance.PersistenceCapable;
import org.apache.openjpa.kernel.FetchConfiguration;
import org.apache.openjpa.kernel.LockManager;
@ -30,7 +30,10 @@ import org.apache.openjpa.kernel.PCState;
import org.apache.openjpa.kernel.StoreContext;
import org.apache.openjpa.kernel.StoreManager;
import org.apache.openjpa.lib.util.Closeable;
import org.apache.openjpa.lib.util.ReferenceMap;
import org.apache.openjpa.lib.util.UUIDGenerator;
import org.apache.openjpa.lib.util.concurrent.ConcurrentHashMap;
import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.meta.JavaTypes;
@ -46,6 +49,10 @@ import org.apache.openjpa.meta.ValueStrategies;
*/
public class ImplHelper {
// Cache for from/to type assignments
private static ConcurrentReferenceHashMap _assignableTypes =
new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD);
/**
* Helper for store manager implementations. This method simply delegates
* to the proper singular method for each state manager.
@ -187,4 +194,34 @@ public class ImplHelper {
public static boolean isManageable(Object instance) {
return instance instanceof PersistenceCapable;
}
/**
* Returns true if the referenced "to" class is assignable to the "from"
* class. This helper method utilizes a cache to help avoid the overhead
* of the Class.isAssignableFrom() method.
*
* @param from target class instance to be checked for assignability
* @param to second class instance to be checked for assignability
* @return true if the "to" class is assignable to the "from" class
*/
public static boolean isAssignable(Class from, Class to) {
Boolean isAssignable = null;
if (from == null || to == null)
return false;
Map assignableTo = (Map) _assignableTypes.get(from);
if (assignableTo == null) { // "to" cache doesn't exist, so create it...
assignableTo = new ConcurrentHashMap();
_assignableTypes.put(from, assignableTo);
} else { // "to" cache exists...
isAssignable = (Boolean) assignableTo.get(to);
}
if (isAssignable == null) {// we don't have a record of this pair...
isAssignable = new Boolean(from.isAssignableFrom(to));
assignableTo.put(to, isAssignable);
}
return isAssignable.booleanValue();
}
}

View File

@ -17,7 +17,6 @@ package org.apache.openjpa.util;
import java.io.Serializable;
import org.apache.openjpa.lib.util.ReferenceHashSet;
import org.apache.openjpa.lib.util.ReferenceMap;
import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap;
@ -37,7 +36,7 @@ public abstract class OpenJPAId
private transient int _typeHash = 0;
// cache the types' generated hashcodes
private static ConcurrentReferenceHashMap _typeCache =
new ConcurrentReferenceHashMap(ReferenceMap.HARD, ReferenceMap.WEAK);
new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD);
protected OpenJPAId() {
}