From 09ea1b33f92ff6eae5b911d32b6ce9e4af781f20 Mon Sep 17 00:00:00 2001 From: Brett Meyer Date: Wed, 12 Feb 2014 13:31:09 -0500 Subject: [PATCH] HHH-8945 introduced "hibernate.session.initial_capacity" to reduce StatefulPersistenceContext's Map#resize calls Conflicts: hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java --- .../org/hibernate/cfg/AvailableSettings.java | 10 ++++ .../internal/StatefulPersistenceContext.java | 56 +++++++++++-------- 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java index 79607e9f2f..34f562cc8c 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java @@ -709,5 +709,15 @@ public interface AvailableSettings { String LOG_SESSION_METRICS = "hibernate.session.events.log"; String AUTO_SESSION_EVENTS_LISTENER = "hibernate.session.events.auto"; + + /** + * A {@link org.hibernate.engine.internal.StatefulPersistenceContext} maintains multiple Maps for a Session. For + * performance reasons, it can be desirable to initialize the Maps with a non-default capacity, minimizing the + * occurrences of #resize calls. The capacity generally correlates with the quantity of entities expected to be + * managed by an average Session. + * + * Default: 8 + */ + String SESSION_INITIAL_CAPACITY = "hibernate.session.initial_capacity"; } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java b/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java index 02d4b8c6a4..446355f8c3 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java @@ -38,8 +38,6 @@ import java.util.Map; import java.util.Map.Entry; -import org.jboss.logging.Logger; - import org.hibernate.AssertionFailure; import org.hibernate.Hibernate; import org.hibernate.HibernateException; @@ -52,6 +50,7 @@ import org.hibernate.cache.spi.NaturalIdCacheKey; import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; import org.hibernate.cache.spi.access.SoftLock; +import org.hibernate.cfg.AvailableSettings; import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.engine.loading.internal.LoadContexts; import org.hibernate.engine.spi.AssociationKey; @@ -76,8 +75,10 @@ import org.hibernate.pretty.MessageHelper; import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; +import org.hibernate.service.config.spi.ConfigurationService; import org.hibernate.tuple.ElementWrapper; import org.hibernate.type.CollectionType; +import org.jboss.logging.Logger; /** * A stateful implementation of the {@link PersistenceContext} contract meaning that we maintain this @@ -93,11 +94,12 @@ public class StatefulPersistenceContext implements PersistenceContext { private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, StatefulPersistenceContext.class.getName() ); - private static final boolean tracing = LOG.isTraceEnabled(); + private static final boolean tracing = LOG.isTraceEnabled(); public static final Object NO_ROW = new MarkerObject( "NO_ROW" ); - public static final int INIT_COLL_SIZE = 8; + private static final int DEFAULT_INITIAL_CAPACITY = 8; + private final int initialCapacity; private SessionImplementor session; @@ -162,20 +164,23 @@ public class StatefulPersistenceContext implements PersistenceContext { */ public StatefulPersistenceContext(SessionImplementor session) { this.session = session; + + initialCapacity = session.getFactory().getServiceRegistry().getService( ConfigurationService.class ) + .getSetting( AvailableSettings.SESSION_INITIAL_CAPACITY, Integer.class, DEFAULT_INITIAL_CAPACITY ); - entitiesByKey = new HashMap( INIT_COLL_SIZE ); - entitiesByUniqueKey = new HashMap( INIT_COLL_SIZE ); + entitiesByKey = new HashMap( initialCapacity ); + entitiesByUniqueKey = new HashMap( initialCapacity ); //noinspection unchecked - proxiesByKey = new ConcurrentReferenceHashMap( INIT_COLL_SIZE, .75f, 1, ConcurrentReferenceHashMap.ReferenceType.STRONG, ConcurrentReferenceHashMap.ReferenceType.WEAK, null ); - entitySnapshotsByKey = new HashMap( INIT_COLL_SIZE ); + proxiesByKey = new ConcurrentReferenceHashMap( initialCapacity, .75f, 1, ConcurrentReferenceHashMap.ReferenceType.STRONG, ConcurrentReferenceHashMap.ReferenceType.WEAK, null ); + entitySnapshotsByKey = new HashMap( initialCapacity ); entityEntryContext = new EntityEntryContext(); -// entityEntries = IdentityMap.instantiateSequenced( INIT_COLL_SIZE ); - collectionEntries = IdentityMap.instantiateSequenced( INIT_COLL_SIZE ); - parentsByChild = new IdentityHashMap( INIT_COLL_SIZE ); +// entityEntries = IdentityMap.instantiateSequenced( initialCapacity ); + collectionEntries = IdentityMap.instantiateSequenced( initialCapacity ); + parentsByChild = new IdentityHashMap( initialCapacity ); - collectionsByKey = new HashMap( INIT_COLL_SIZE ); - arrayHolders = new IdentityHashMap( INIT_COLL_SIZE ); + collectionsByKey = new HashMap( initialCapacity ); + arrayHolders = new IdentityHashMap( initialCapacity ); nullifiableEntityKeys = new HashSet(); @@ -183,8 +188,8 @@ public StatefulPersistenceContext(SessionImplementor session) { } private void initTransientState() { - nullAssociations = new HashSet( INIT_COLL_SIZE ); - nonlazyCollections = new ArrayList( INIT_COLL_SIZE ); + nullAssociations = new HashSet( initialCapacity ); + nonlazyCollections = new ArrayList( initialCapacity ); } @Override @@ -208,7 +213,7 @@ public LoadContexts getLoadContexts() { @Override public void addUnownedCollection(CollectionKey key, PersistentCollection collection) { if (unownedCollections==null) { - unownedCollections = new HashMap(INIT_COLL_SIZE); + unownedCollections = new HashMap(initialCapacity); } unownedCollections.put( key, collection ); } @@ -1659,6 +1664,9 @@ public static StatefulPersistenceContext deserialize( } final StatefulPersistenceContext rtn = new StatefulPersistenceContext( session ); SessionFactoryImplementor sfi = session.getFactory(); + + int initialCapacity = sfi.getServiceRegistry().getService( ConfigurationService.class ) + .getSetting( AvailableSettings.SESSION_INITIAL_CAPACITY, Integer.class, DEFAULT_INITIAL_CAPACITY ); // during deserialization, we need to reconnect all proxies and // collections to this session, as well as the EntityEntry and @@ -1672,14 +1680,14 @@ public static StatefulPersistenceContext deserialize( int count = ois.readInt(); if ( tracing ) LOG.trace("Starting deserialization of [" + count + "] entitiesByKey entries"); - rtn.entitiesByKey = new HashMap( count < INIT_COLL_SIZE ? INIT_COLL_SIZE : count ); + rtn.entitiesByKey = new HashMap( count < initialCapacity ? initialCapacity : count ); for ( int i = 0; i < count; i++ ) { rtn.entitiesByKey.put( EntityKey.deserialize( ois, sfi ), ois.readObject() ); } count = ois.readInt(); if ( tracing ) LOG.trace("Starting deserialization of [" + count + "] entitiesByUniqueKey entries"); - rtn.entitiesByUniqueKey = new HashMap( count < INIT_COLL_SIZE ? INIT_COLL_SIZE : count ); + rtn.entitiesByUniqueKey = new HashMap( count < initialCapacity ? initialCapacity : count ); for ( int i = 0; i < count; i++ ) { rtn.entitiesByUniqueKey.put( EntityUniqueKey.deserialize( ois, session ), ois.readObject() ); } @@ -1688,7 +1696,7 @@ public static StatefulPersistenceContext deserialize( if ( tracing ) LOG.trace("Starting deserialization of [" + count + "] proxiesByKey entries"); //noinspection unchecked rtn.proxiesByKey = new ConcurrentReferenceHashMap( - count < INIT_COLL_SIZE ? INIT_COLL_SIZE : count, + count < initialCapacity ? initialCapacity : count, .75f, 1, ConcurrentReferenceHashMap.ReferenceType.STRONG, @@ -1709,7 +1717,7 @@ public static StatefulPersistenceContext deserialize( count = ois.readInt(); if ( tracing ) LOG.trace("Starting deserialization of [" + count + "] entitySnapshotsByKey entries"); - rtn.entitySnapshotsByKey = new HashMap( count < INIT_COLL_SIZE ? INIT_COLL_SIZE : count ); + rtn.entitySnapshotsByKey = new HashMap( count < initialCapacity ? initialCapacity : count ); for ( int i = 0; i < count; i++ ) { rtn.entitySnapshotsByKey.put( EntityKey.deserialize( ois, sfi ), ois.readObject() ); } @@ -1717,7 +1725,7 @@ public static StatefulPersistenceContext deserialize( rtn.entityEntryContext = EntityEntryContext.deserialize( ois, rtn ); // count = ois.readInt(); // if ( tracing ) LOG.trace("Starting deserialization of [" + count + "] entityEntries entries"); -// rtn.entityEntries = IdentityMap.instantiateSequenced( count < INIT_COLL_SIZE ? INIT_COLL_SIZE : count ); +// rtn.entityEntries = IdentityMap.instantiateSequenced( count < initialCapacity ? initialCapacity : count ); // for ( int i = 0; i < count; i++ ) { // Object entity = ois.readObject(); // EntityEntry entry = EntityEntry.deserialize( ois, rtn ); @@ -1726,14 +1734,14 @@ public static StatefulPersistenceContext deserialize( count = ois.readInt(); if ( tracing ) LOG.trace("Starting deserialization of [" + count + "] collectionsByKey entries"); - rtn.collectionsByKey = new HashMap( count < INIT_COLL_SIZE ? INIT_COLL_SIZE : count ); + rtn.collectionsByKey = new HashMap( count < initialCapacity ? initialCapacity : count ); for ( int i = 0; i < count; i++ ) { rtn.collectionsByKey.put( CollectionKey.deserialize( ois, session ), (PersistentCollection) ois.readObject() ); } count = ois.readInt(); if ( tracing ) LOG.trace("Starting deserialization of [" + count + "] collectionEntries entries"); - rtn.collectionEntries = IdentityMap.instantiateSequenced( count < INIT_COLL_SIZE ? INIT_COLL_SIZE : count ); + rtn.collectionEntries = IdentityMap.instantiateSequenced( count < initialCapacity ? initialCapacity : count ); for ( int i = 0; i < count; i++ ) { final PersistentCollection pc = ( PersistentCollection ) ois.readObject(); final CollectionEntry ce = CollectionEntry.deserialize( ois, session ); @@ -1743,7 +1751,7 @@ public static StatefulPersistenceContext deserialize( count = ois.readInt(); if ( tracing ) LOG.trace("Starting deserialization of [" + count + "] arrayHolders entries"); - rtn.arrayHolders = new IdentityHashMap( count < INIT_COLL_SIZE ? INIT_COLL_SIZE : count ); + rtn.arrayHolders = new IdentityHashMap( count < initialCapacity ? initialCapacity : count ); for ( int i = 0; i < count; i++ ) { rtn.arrayHolders.put( ois.readObject(), (PersistentCollection) ois.readObject() ); }