HHH-15976 Further optimise InitializersList to avoid resizing collections
This commit is contained in:
parent
04becd0aa4
commit
1e87b3399f
|
@ -7,7 +7,7 @@
|
||||||
package org.hibernate.sql.results.internal;
|
package org.hibernate.sql.results.internal;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -22,38 +22,36 @@ import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
||||||
* Internal helper to keep track of the various
|
* Internal helper to keep track of the various
|
||||||
* Initializer instances being used during RowReader processing:
|
* Initializer instances being used during RowReader processing:
|
||||||
* different types of initializers need to be invoked in different orders,
|
* different types of initializers need to be invoked in different orders,
|
||||||
* so rather than finding them during each row we keep separated lists
|
* so rather than having to identify the order of initializers again during
|
||||||
* of initializers defined upfront and then reused for the scope of the whole
|
* the processing of each row we keep separated lists of initializers defined
|
||||||
* resultset.
|
* upfront and then reuse these sets for the scope of the whole resultset's
|
||||||
|
* processing.
|
||||||
|
* @author Sanne Grinovero
|
||||||
*/
|
*/
|
||||||
public final class InitializersList {
|
public final class InitializersList {
|
||||||
private final List<Initializer> initializers;
|
|
||||||
private final List<Initializer> collectionInitializers;
|
private final Initializer[] initializers;
|
||||||
private final List<Initializer> nonCollectionInitializers;
|
private final Initializer[] sortedNonCollectionsFirst;
|
||||||
private final List<Initializer> resolveInstanceFirstInitializers;
|
private final Initializer[] sortedForResolveInstance;
|
||||||
private final List<Initializer> resolveInstanceLaterInitializers;
|
|
||||||
private final boolean hasCollectionInitializers;
|
private final boolean hasCollectionInitializers;
|
||||||
private final Map<NavigablePath, Initializer> initializerMap;
|
private final Map<NavigablePath, Initializer> initializerMap;
|
||||||
|
|
||||||
private InitializersList(
|
private InitializersList(
|
||||||
List<Initializer> initializers,
|
Initializer[] initializers,
|
||||||
List<Initializer> collectionInitializers,
|
Initializer[] sortedNonCollectionsFirst,
|
||||||
List<Initializer> nonCollectionInitializers,
|
Initializer[] sortedForResolveInstance,
|
||||||
List<Initializer> resolveInstanceFirstInitializers,
|
boolean hasCollectionInitializers,
|
||||||
List<Initializer> resolveInstanceLaterInitializers,
|
|
||||||
Map<NavigablePath, Initializer> initializerMap) {
|
Map<NavigablePath, Initializer> initializerMap) {
|
||||||
this.initializers = initializers;
|
this.initializers = initializers;
|
||||||
this.collectionInitializers = collectionInitializers;
|
this.sortedNonCollectionsFirst = sortedNonCollectionsFirst;
|
||||||
this.nonCollectionInitializers = nonCollectionInitializers;
|
this.sortedForResolveInstance = sortedForResolveInstance;
|
||||||
this.resolveInstanceFirstInitializers = resolveInstanceFirstInitializers;
|
this.hasCollectionInitializers = hasCollectionInitializers;
|
||||||
this.resolveInstanceLaterInitializers = resolveInstanceLaterInitializers;
|
|
||||||
this.hasCollectionInitializers = ! collectionInitializers.isEmpty();
|
|
||||||
this.initializerMap = initializerMap;
|
this.initializerMap = initializerMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated //for simpler migration to the new SPI
|
@Deprecated //for simpler migration to the new SPI
|
||||||
public List<Initializer> asList() {
|
public List<Initializer> asList() {
|
||||||
return initializers;
|
return Arrays.asList( initializers );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Initializer resolveInitializer(final NavigablePath path) {
|
public Initializer resolveInitializer(final NavigablePath path) {
|
||||||
|
@ -79,19 +77,13 @@ public final class InitializersList {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resolveKeys(final RowProcessingState rowProcessingState) {
|
public void resolveKeys(final RowProcessingState rowProcessingState) {
|
||||||
for ( Initializer init : nonCollectionInitializers ) {
|
for ( Initializer init : sortedNonCollectionsFirst ) {
|
||||||
init.resolveKey( rowProcessingState );
|
|
||||||
}
|
|
||||||
for ( Initializer init : collectionInitializers ) {
|
|
||||||
init.resolveKey( rowProcessingState );
|
init.resolveKey( rowProcessingState );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resolveInstances(final RowProcessingState rowProcessingState) {
|
public void resolveInstances(final RowProcessingState rowProcessingState) {
|
||||||
for ( Initializer init : resolveInstanceFirstInitializers ) {
|
for ( Initializer init : sortedForResolveInstance ) {
|
||||||
init.resolveInstance( rowProcessingState );
|
|
||||||
}
|
|
||||||
for ( Initializer init : resolveInstanceLaterInitializers ) {
|
|
||||||
init.resolveInstance( rowProcessingState );
|
init.resolveInstance( rowProcessingState );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,53 +93,68 @@ public final class InitializersList {
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Builder {
|
static class Builder {
|
||||||
private List<Initializer> initializers = new ArrayList<>();
|
private ArrayList<Initializer> initializers = new ArrayList<>();
|
||||||
private List<Initializer> collectionInitializers;
|
int nonCollectionInitializersNum = 0;
|
||||||
private List<Initializer> nonCollectionInitializers;
|
int resolveFirstNum = 0;
|
||||||
private List<Initializer> resolveInstanceFirstInitializers;
|
|
||||||
private List<Initializer> resolveInstanceLaterInitializers;
|
|
||||||
|
|
||||||
public Builder() {}
|
public Builder() {}
|
||||||
|
|
||||||
public void addInitializer(Initializer initializer) {
|
public void addInitializer(final Initializer initializer) {
|
||||||
initializers.add( initializer );
|
initializers.add( initializer );
|
||||||
if ( initializer.isCollectionInitializer() ) {
|
//in this method we perform these checks merely to learn the sizing hints,
|
||||||
if ( collectionInitializers == null ) {
|
//so to not need dynamically scaling collections.
|
||||||
collectionInitializers = new ArrayList<>();
|
//This implies performing both checks twice but since they're cheap it's preferrable
|
||||||
|
//to multiple allocations; not least this allows using arrays, which makes iteration
|
||||||
|
//cheaper during the row processing - which is very hot.
|
||||||
|
if ( !initializer.isCollectionInitializer() ) {
|
||||||
|
nonCollectionInitializersNum++;
|
||||||
}
|
}
|
||||||
collectionInitializers.add( initializer );
|
if ( initializeFirst( initializer ) ) {
|
||||||
}
|
resolveFirstNum++;
|
||||||
else {
|
|
||||||
if ( nonCollectionInitializers == null ) {
|
|
||||||
nonCollectionInitializers = new ArrayList<>();
|
|
||||||
}
|
|
||||||
nonCollectionInitializers.add( initializer );
|
|
||||||
}
|
|
||||||
if ( !( initializer instanceof EntityDelayedFetchInitializer ) && ! (initializer instanceof EntitySelectFetchInitializer ) ) {
|
|
||||||
if ( resolveInstanceFirstInitializers == null ) {
|
|
||||||
resolveInstanceFirstInitializers = new ArrayList<>();
|
|
||||||
}
|
|
||||||
resolveInstanceFirstInitializers.add( initializer );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ( resolveInstanceLaterInitializers == null ) {
|
|
||||||
resolveInstanceLaterInitializers = new ArrayList<>();
|
|
||||||
}
|
|
||||||
resolveInstanceLaterInitializers.add( initializer );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InitializersList build(Map<NavigablePath, Initializer> initializerMap) {
|
private static boolean initializeFirst(final Initializer initializer) {
|
||||||
|
return !( initializer instanceof EntityDelayedFetchInitializer ) && !( initializer instanceof EntitySelectFetchInitializer );
|
||||||
|
}
|
||||||
|
|
||||||
|
InitializersList build(final Map<NavigablePath, Initializer> initializerMap) {
|
||||||
|
final int size = initializers.size();
|
||||||
|
final Initializer[] sortedNonCollectionsFirst = new Initializer[size];
|
||||||
|
final Initializer[] sortedForResolveInstance = new Initializer[size];
|
||||||
|
int nonCollectionIdx = 0;
|
||||||
|
int collectionIdx = nonCollectionInitializersNum;
|
||||||
|
int resolveFirstIdx = 0;
|
||||||
|
int resolveLaterIdx = resolveFirstNum;
|
||||||
|
final Initializer[] originalSortInitializers = toArray( initializers );
|
||||||
|
for ( Initializer initializer : originalSortInitializers ) {
|
||||||
|
if ( initializer.isCollectionInitializer() ) {
|
||||||
|
sortedNonCollectionsFirst[collectionIdx++] = initializer;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sortedNonCollectionsFirst[nonCollectionIdx++] = initializer;
|
||||||
|
}
|
||||||
|
if ( initializeFirst( initializer ) ) {
|
||||||
|
sortedForResolveInstance[resolveFirstIdx++] = initializer;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sortedForResolveInstance[resolveLaterIdx++] = initializer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final boolean hasCollectionInitializers = ( nonCollectionInitializersNum != initializers.size() );
|
||||||
return new InitializersList(
|
return new InitializersList(
|
||||||
initializers,
|
originalSortInitializers,
|
||||||
collectionInitializers == null ? Collections.EMPTY_LIST : collectionInitializers,
|
sortedNonCollectionsFirst,
|
||||||
nonCollectionInitializers == null ? Collections.EMPTY_LIST : nonCollectionInitializers,
|
sortedForResolveInstance,
|
||||||
resolveInstanceFirstInitializers == null ? Collections.EMPTY_LIST : resolveInstanceFirstInitializers,
|
hasCollectionInitializers,
|
||||||
resolveInstanceLaterInitializers == null ? Collections.EMPTY_LIST : resolveInstanceLaterInitializers,
|
|
||||||
initializerMap
|
initializerMap
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Initializer[] toArray(final ArrayList<Initializer> initializers) {
|
||||||
|
return initializers.toArray( new Initializer[initializers.size()] );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue