Author: ste...@jb... Date: 2006-07-05 14:17:27 -0400 (Wed, 05 Jul 2006) New Revision: 10086 Modified: trunk/Hibernate3/src/org/hibernate/collection/PersistentArrayHolder.java trunk/Hibernate3/src/org/hibernate/collection/PersistentBag.java trunk/Hibernate3/src/org/hibernate/collection/PersistentCollection.java trunk/Hibernate3/src/org/hibernate/collection/PersistentElementHolder.java trunk/Hibernate3/src/org/hibernate/collection/PersistentIdentifierBag.java trunk/Hibernate3/src/org/hibernate/collection/PersistentIndexedElementHolder.java trunk/Hibernate3/src/org/hibernate/collection/PersistentList.java trunk/Hibernate3/src/org/hibernate/collection/PersistentMap.java trunk/Hibernate3/src/org/hibernate/collection/PersistentSet.java trunk/Hibernate3/src/org/hibernate/engine/CollectionLoadContext.java trunk/Hibernate3/src/org/hibernate/type/ArrayType.java trunk/Hibernate3/src/org/hibernate/type/BagType.java trunk/Hibernate3/src/org/hibernate/type/CollectionType.java trunk/Hibernate3/src/org/hibernate/type/CustomCollectionType.java trunk/Hibernate3/src/org/hibernate/type/IdentifierBagType.java trunk/Hibernate3/src/org/hibernate/type/ListType.java trunk/Hibernate3/src/org/hibernate/type/MapType.java trunk/Hibernate3/src/org/hibernate/type/SetType.java trunk/Hibernate3/src/org/hibernate/usertype/UserCollectionType.java trunk/Hibernate3/test/org/hibernate/test/usercollection/MyListType.java trunk/Hibernate3/test/org/hibernate/test/usercollection/UserCollectionTypeTest.java Log: HHH-1789 : proper collection sizing for improved performance Modified: trunk/Hibernate3/src/org/hibernate/collection/PersistentArrayHolder.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/collection/PersistentArrayHolder.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/src/org/hibernate/collection/PersistentArrayHolder.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -137,7 +137,7 @@ return true; } - public void beforeInitialize(CollectionPersister persister) { + public void beforeInitialize(CollectionPersister persister, int anticipatedSize) { //if (tempList==null) throw new UnsupportedOperationException("Can't lazily initialize arrays"); } Modified: trunk/Hibernate3/src/org/hibernate/collection/PersistentBag.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/collection/PersistentBag.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/src/org/hibernate/collection/PersistentBag.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -71,8 +71,8 @@ return element; } - public void beforeInitialize(CollectionPersister persister) { - this.bag = (List) persister.getCollectionType().instantiate(); + public void beforeInitialize(CollectionPersister persister, int anticipatedSize) { + this.bag = ( List ) persister.getCollectionType().instantiate( anticipatedSize ); } public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException { @@ -134,11 +134,14 @@ public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner) throws HibernateException { - beforeInitialize(persister); Serializable[] array = (Serializable[]) disassembled; - for ( int i=0; i<array.length; i++ ) { + int size = array.length; + beforeInitialize( persister, size ); + for ( int i = 0; i < size; i++ ) { Object element = persister.getElementType().assemble( array[i], getSession(), owner ); - if ( element!=null ) bag.add( element ); + if ( element!=null ) { + bag.add( element ); + } } } Modified: trunk/Hibernate3/src/org/hibernate/collection/PersistentCollection.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/collection/PersistentCollection.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/src/org/hibernate/collection/PersistentCollection.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -151,8 +151,11 @@ /** * Called before any elements are read into the collection, * allowing appropriate initializations to occur. + * + * @param persister The underlying collection persister. + * @param anticipatedSize The anticipated size of the collection after initilization is complete. */ - public void beforeInitialize(CollectionPersister persister); + public void beforeInitialize(CollectionPersister persister, int anticipatedSize); /** * Does the current state exactly match the snapshot? Modified: trunk/Hibernate3/src/org/hibernate/collection/PersistentElementHolder.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/collection/PersistentElementHolder.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/src/org/hibernate/collection/PersistentElementHolder.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -120,7 +120,7 @@ return result.iterator(); } - public void beforeInitialize(CollectionPersister persister) {} + public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {} public boolean isDirectlyAccessible() { return true; Modified: trunk/Hibernate3/src/org/hibernate/collection/PersistentIdentifierBag.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/collection/PersistentIdentifierBag.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/src/org/hibernate/collection/PersistentIdentifierBag.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -61,9 +61,10 @@ public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner) throws HibernateException { - beforeInitialize(persister); Serializable[] array = (Serializable[]) disassembled; - for ( int i=0; i<array.length; i+=2 ) { + int size = array.length; + beforeInitialize( persister, size ); + for ( int i = 0; i < size; i+=2 ) { identifiers.put( new Integer(i/2), persister.getIdentifierType().assemble( array[i], getSession(), owner ) @@ -159,14 +160,13 @@ return values.toArray(a); } - public void beforeInitialize(CollectionPersister persister) { - identifiers = new HashMap(); - values = new ArrayList(); + public void beforeInitialize(CollectionPersister persister, int anticipatedSize) { + identifiers = anticipatedSize <= 0 ? new HashMap() : new HashMap( anticipatedSize + 1 + (int)( anticipatedSize * .75f ), .75f ); + values = anticipatedSize <= 0 ? new ArrayList() : new ArrayList( anticipatedSize ); } public Serializable disassemble(CollectionPersister persister) - throws HibernateException { - + throws HibernateException { Serializable[] result = new Serializable[ values.size() * 2 ]; int i=0; for (int j=0; j< values.size(); j++) { Modified: trunk/Hibernate3/src/org/hibernate/collection/PersistentIndexedElementHolder.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/collection/PersistentIndexedElementHolder.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/src/org/hibernate/collection/PersistentIndexedElementHolder.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -161,7 +161,7 @@ return result.iterator(); } - public void beforeInitialize(CollectionPersister persister) {} + public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {} public boolean isDirectlyAccessible() { return true; Modified: trunk/Hibernate3/src/org/hibernate/collection/PersistentList.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/collection/PersistentList.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/src/org/hibernate/collection/PersistentList.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -74,8 +74,8 @@ setDirectlyAccessible(true); } - public void beforeInitialize(CollectionPersister persister) { - this.list = (List) persister.getCollectionType().instantiate(); + public void beforeInitialize(CollectionPersister persister, int anticipatedSize) { + this.list = ( List ) persister.getCollectionType().instantiate( anticipatedSize ); } public boolean isWrapper(Object collection) { @@ -372,9 +372,10 @@ public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner) throws HibernateException { - beforeInitialize(persister); - Serializable[] array = (Serializable[]) disassembled; - for ( int i=0; i<array.length; i++ ) { + Serializable[] array = ( Serializable[] ) disassembled; + int size = array.length; + beforeInitialize( persister, size ); + for ( int i = 0; i < size; i++ ) { list.add( persister.getElementType().assemble( array[i], getSession(), owner ) ); } } Modified: trunk/Hibernate3/src/org/hibernate/collection/PersistentMap.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/collection/PersistentMap.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/src/org/hibernate/collection/PersistentMap.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -31,10 +31,8 @@ protected Map map; - public Serializable getSnapshot(CollectionPersister persister) - throws HibernateException { + public Serializable getSnapshot(CollectionPersister persister) throws HibernateException { EntityMode entityMode = getSession().getEntityMode(); - HashMap clonedMap = new HashMap( map.size() ); Iterator iter = map.entrySet().iterator(); while ( iter.hasNext() ) { @@ -77,8 +75,8 @@ public PersistentMap() {} //needed for SOAP libraries, etc - public void beforeInitialize(CollectionPersister persister) { - this.map = (Map) persister.getCollectionType().instantiate(); + public void beforeInitialize(CollectionPersister persister, int anticipatedSize) { + this.map = ( Map ) persister.getCollectionType().instantiate( anticipatedSize ); } public PersistentMap(SessionImplementor session, Map map) { @@ -317,9 +315,10 @@ public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner) throws HibernateException { - beforeInitialize(persister); - Serializable[] array = (Serializable[]) disassembled; - for (int i=0; i<array.length; i+=2 ) { + Serializable[] array = ( Serializable[] ) disassembled; + int size = array.length; + beforeInitialize( persister, size ); + for ( int i = 0; i < size; i+=2 ) { map.put( persister.getIndexType().assemble( array[i], getSession(), owner ), persister.getElementType().assemble( array[i+1], getSession(), owner ) Modified: trunk/Hibernate3/src/org/hibernate/collection/PersistentSet.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/collection/PersistentSet.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/src/org/hibernate/collection/PersistentSet.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -78,8 +78,8 @@ public PersistentSet() {} //needed for SOAP libraries, etc - public void beforeInitialize(CollectionPersister persister) { - this.set = (Set) persister.getCollectionType().instantiate(); + public void beforeInitialize(CollectionPersister persister, int anticipatedSize) { + this.set = ( Set ) persister.getCollectionType().instantiate( anticipatedSize ); } public PersistentSet(SessionImplementor session, java.util.Set set) { @@ -95,11 +95,14 @@ public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner) throws HibernateException { - beforeInitialize(persister); - Serializable[] array = (Serializable[]) disassembled; - for (int i=0; i<array.length; i++ ) { + Serializable[] array = ( Serializable[] ) disassembled; + int size = array.length; + beforeInitialize( persister, size ); + for (int i = 0; i < size; i++ ) { Object element = persister.getElementType().assemble( array[i], getSession(), owner ); - if (element!=null) set.add(element); + if ( element != null ) { + set.add( element ); + } } } Modified: trunk/Hibernate3/src/org/hibernate/engine/CollectionLoadContext.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/engine/CollectionLoadContext.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/src/org/hibernate/engine/CollectionLoadContext.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -102,7 +102,7 @@ .instantiate( context.getSession(), persister, key ); } } - collection.beforeInitialize(persister); + collection.beforeInitialize( persister, -1 ); collection.beginRead(); addLoadingCollectionEntry(ckey, collection, persister, resultSetId); return collection; Modified: trunk/Hibernate3/src/org/hibernate/type/ArrayType.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/type/ArrayType.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/src/org/hibernate/type/ArrayType.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -96,7 +96,7 @@ } - public Object instantiate() { + public Object instantiate(int anticipatedSize) { throw new UnsupportedOperationException(); } Modified: trunk/Hibernate3/src/org/hibernate/type/BagType.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/type/BagType.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/src/org/hibernate/type/BagType.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -43,9 +43,8 @@ } } - public Object instantiate() { - //TODO: does not work for EntityMode.DOM4J yet - return new ArrayList(); + public Object instantiate(int anticipatedSize) { + return anticipatedSize <= 0 ? new ArrayList() : new ArrayList( anticipatedSize + 1 ); } } Modified: trunk/Hibernate3/src/org/hibernate/type/CollectionType.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/type/CollectionType.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/src/org/hibernate/type/CollectionType.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -418,15 +418,29 @@ return result; } - - public Object instantiateResult(Object original) { - return instantiate(); + + /** + * Instantiate a new "underlying" collection exhibiting the same capacity + * charactersitcs and the passed "original". + * + * @param original The original collection. + * @return The newly instantiated collection. + */ + protected Object instantiateResult(Object original) { + // by default just use an unanticipated capacity since we don't + // know how to extract the capacity to use from original here... + return instantiate( -1 ); } /** - * Instantiate an empty instance of the "underlying" collection (not a wrapper) + * Instantiate an empty instance of the "underlying" collection (not a wrapper), + * but with the given anticipated size (i.e. accounting for initial capacity + * and perhaps load factor). + * + * @param anticipatedSize The anticipated size of the instaniated collection + * after we are done populating it. */ - public abstract Object instantiate(); + public abstract Object instantiate(int anticipatedSize); public Object replace( final Object original, @@ -436,12 +450,17 @@ final Map copyCache) throws HibernateException { - if ( original == null ) return null; - if ( !Hibernate.isInitialized( original ) ) return target; + if ( original == null ) { + return null; + } + if ( !Hibernate.isInitialized( original ) ) { + return target; + } //if ( original == target ) return target; // can't do this, since need to merge element references - Object result = target==null || target==original ? //instead, put the merged elements in a new collection - instantiateResult( original ) : target; + // for a null target, or a target which is the same as the original, we + // need to put the merged elements in a new collection + Object result = target == null || target == original ? instantiateResult( original ) : target; //for arrays, replaceElements() may return a different reference, since //the array length might not match Modified: trunk/Hibernate3/src/org/hibernate/type/CustomCollectionType.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/type/CustomCollectionType.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/src/org/hibernate/type/CustomCollectionType.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -7,7 +7,6 @@ import org.hibernate.HibernateException; import org.hibernate.MappingException; -import org.hibernate.Hibernate; import org.hibernate.collection.PersistentCollection; import org.hibernate.engine.SessionImplementor; import org.hibernate.engine.SessionFactoryImplementor; @@ -57,11 +56,11 @@ } public Class getReturnedClass() { - return userType.instantiate().getClass(); + return userType.instantiate( -1 ).getClass(); } - public Object instantiate() { - return userType.instantiate(); + public Object instantiate(int anticipatedType) { + return userType.instantiate( anticipatedType ); } public Iterator getElementsIterator(Object collection) { Modified: trunk/Hibernate3/src/org/hibernate/type/IdentifierBagType.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/type/IdentifierBagType.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/src/org/hibernate/type/IdentifierBagType.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -24,8 +24,8 @@ return new PersistentIdentifierBag(session); } - public Object instantiate() { - return new ArrayList(); + public Object instantiate(int anticipatedSize) { + return anticipatedSize <= 0 ? new ArrayList() : new ArrayList( anticipatedSize + 1 ); } public Class getReturnedClass() { Modified: trunk/Hibernate3/src/org/hibernate/type/ListType.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/type/ListType.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/src/org/hibernate/type/ListType.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -41,8 +41,8 @@ } } - public Object instantiate() { - return new ArrayList(); + public Object instantiate(int anticipatedSize) { + return anticipatedSize <= 0 ? new ArrayList() : new ArrayList( anticipatedSize + 1 ); } public Object indexOf(Object collection, Object element) { Modified: trunk/Hibernate3/src/org/hibernate/type/MapType.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/type/MapType.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/src/org/hibernate/type/MapType.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -48,8 +48,10 @@ } } - public Object instantiate() { - return new HashMap(); + public Object instantiate(int anticipatedSize) { + return anticipatedSize <= 0 + ? new HashMap() + : new HashMap( anticipatedSize + (int)( anticipatedSize * .75f ), .75f ); } public Object replaceElements( Modified: trunk/Hibernate3/src/org/hibernate/type/SetType.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/type/SetType.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/src/org/hibernate/type/SetType.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -40,9 +40,10 @@ } } - public Object instantiate() { - //TODO: Might need to be a LinkedHashSet!!!!!! - return new HashSet(); + public Object instantiate(int anticipatedSize) { + return anticipatedSize <= 0 + ? new HashSet() + : new HashSet( anticipatedSize + (int)( anticipatedSize * .75f ), .75f ); } } Modified: trunk/Hibernate3/src/org/hibernate/usertype/UserCollectionType.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/usertype/UserCollectionType.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/src/org/hibernate/usertype/UserCollectionType.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -54,10 +54,17 @@ Map copyCache, SessionImplementor session) throws HibernateException; - + /** - * Instantiate an empty instance of the "underlying" collection (not a wrapper) + * Instantiate an empty instance of the "underlying" collection (not a wrapper), + * but with the given anticipated size (i.e. accounting for initial size + * and perhaps load factor). + * + * @param anticipatedSize The anticipated size of the instaniated collection + * after we are done populating it. Note, may be negative to indicate that + * we not yet know anything about the anticipated size (i.e., when initializing + * from a result set row by row). */ - public Object instantiate(); + public Object instantiate(int anticipatedSize); } Modified: trunk/Hibernate3/test/org/hibernate/test/usercollection/MyListType.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/usercollection/MyListType.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/test/org/hibernate/test/usercollection/MyListType.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -12,6 +12,8 @@ public class MyListType implements UserCollectionType { + static int lastInstantiationRequest = -2; + public PersistentCollection instantiate(SessionImplementor session, CollectionPersister persister) throws HibernateException { return new PersistentMyList(session); } @@ -43,18 +45,14 @@ } public Object replaceElements(Object original, Object target, CollectionPersister persister, Object owner, Map copyCache, SessionImplementor session) throws HibernateException { - IMyList result = (IMyList) target; - result.clear(); - result.addAll((MyList)original); - return result; - } - public Object instantiate() { + public Object instantiate(int anticipatedSize) { + lastInstantiationRequest = anticipatedSize; return new MyList(); } Modified: trunk/Hibernate3/test/org/hibernate/test/usercollection/UserCollectionTypeTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/usercollection/UserCollectionTypeTest.java 2006-07-05 16:35:26 UTC (rev 10085) +++ trunk/Hibernate3/test/org/hibernate/test/usercollection/UserCollectionTypeTest.java 2006-07-05 18:17:27 UTC (rev 10086) @@ -33,9 +33,22 @@ User u2 = (User) s.createCriteria(User.class).uniqueResult(); assertTrue( Hibernate.isInitialized( u2.getEmailAddresses() ) ); assertEquals( u2.getEmailAddresses().size(), 2 ); - s.delete(u2); t.commit(); s.close(); + + s = openSession(); + t = s.beginTransaction(); + u2 = ( User ) s.get( User.class, u.getUserName() ); + u2.getEmailAddresses().size(); + assertEquals( 2, MyListType.lastInstantiationRequest ); + t.commit(); + s.close(); + + s = openSession(); + t = s.beginTransaction(); + s.delete( u ); + t.commit(); + s.close(); } |