From 7f4373f7b941f88716c08033f1c84100dfd348ad Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Sun, 1 Nov 2020 21:18:17 +0000 Subject: [PATCH] HHH-14305 Memory optimisations for ReaderCollector implementations --- .../internal/AbstractLoadQueryDetails.java | 44 +++++++++++++------ .../process/internal/AbstractRowReader.java | 9 +--- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/internal/AbstractLoadQueryDetails.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/internal/AbstractLoadQueryDetails.java index 2fef82a0f0..aec2181d1b 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/internal/AbstractLoadQueryDetails.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/internal/AbstractLoadQueryDetails.java @@ -7,6 +7,7 @@ package org.hibernate.loader.plan.exec.internal; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.hibernate.engine.spi.SessionFactoryImplementor; @@ -263,45 +264,62 @@ public abstract class AbstractLoadQueryDetails implements LoadQueryDetails { } protected abstract static class ReaderCollectorImpl implements ReaderCollector { - private final List entityReferenceInitializers = new ArrayList(); + private List entityReferenceInitializers; private List arrayReferenceInitializers; private List collectionReferenceInitializers; @Override public void add(CollectionReferenceInitializer collectionReferenceInitializer) { if ( collectionReferenceInitializer.getCollectionReference().getCollectionPersister().isArray() ) { - if ( arrayReferenceInitializers == null ) { - arrayReferenceInitializers = new ArrayList(); - } - arrayReferenceInitializers.add( collectionReferenceInitializer ); + arrayReferenceInitializers = addTo( arrayReferenceInitializers, collectionReferenceInitializer ); } else { - if ( collectionReferenceInitializers == null ) { - collectionReferenceInitializers = new ArrayList(); - } - collectionReferenceInitializers.add( collectionReferenceInitializer ); + collectionReferenceInitializers = addTo( collectionReferenceInitializers, collectionReferenceInitializer ); } } + /** + * LISP-style list growing, as there is a strong likelihood we'll be dealing with lists of zero or one element + * we can save some memory. + * @param host + * @param element + * @param + * @return possibly a new list instance, containing both the original elements and the new elements. + */ + private static List addTo(List host, V element) { + List output = host; + if ( output == null ) { + output = Collections.singletonList( element ); + } + else if ( output.size() == 1 ) { + output = new ArrayList( output ); + output.add( element ); + } + else { + output.add( element ); + } + return output; + } + @Override public void add(EntityReferenceInitializer entityReferenceInitializer) { - entityReferenceInitializers.add( entityReferenceInitializer ); + entityReferenceInitializers = addTo( entityReferenceInitializers, entityReferenceInitializer ); } @Override public final List getEntityReferenceInitializers() { - return entityReferenceInitializers; + return entityReferenceInitializers == null ? Collections.EMPTY_LIST : entityReferenceInitializers; } @Override public List getArrayReferenceInitializers() { - return arrayReferenceInitializers; + return arrayReferenceInitializers == null ? Collections.EMPTY_LIST : arrayReferenceInitializers; } @Override public List getNonArrayCollectionReferenceInitializers() { - return collectionReferenceInitializers; + return collectionReferenceInitializers == null ? Collections.EMPTY_LIST : collectionReferenceInitializers; } } } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/process/internal/AbstractRowReader.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/process/internal/AbstractRowReader.java index c05fb871e5..121e38af3e 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/process/internal/AbstractRowReader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/exec/process/internal/AbstractRowReader.java @@ -72,13 +72,8 @@ public abstract class AbstractRowReader implements RowReader { entityReferenceInitializers = Collections.emptyList(); entityInitializerByEntityReference = Collections.emptyMap(); } - this.arrayReferenceInitializers = CollectionHelper.isNotEmpty( readerCollector.getArrayReferenceInitializers() ) - ? new ArrayList( readerCollector.getArrayReferenceInitializers() ) - : Collections.emptyList(); - this.collectionReferenceInitializers = - CollectionHelper.isNotEmpty ( readerCollector.getNonArrayCollectionReferenceInitializers() ) - ? new ArrayList( readerCollector.getNonArrayCollectionReferenceInitializers() ) - : Collections.emptyList(); + this.arrayReferenceInitializers = readerCollector.getArrayReferenceInitializers(); + this.collectionReferenceInitializers = readerCollector.getNonArrayCollectionReferenceInitializers(); } protected abstract Object readLogicalRow(ResultSet resultSet, ResultSetProcessingContextImpl context)