Skip to content

Commit cf44c30

Browse files
beikovsebersole
authored andcommitted
HHH-18271 Improve fast path for row reading
1 parent e9513b1 commit cf44c30

File tree

6 files changed

+98
-130
lines changed

6 files changed

+98
-130
lines changed

hibernate-core/src/main/java/org/hibernate/loader/ast/internal/DatabaseSnapshotExecutor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
import org.hibernate.sql.exec.spi.JdbcParametersList;
4141
import org.hibernate.sql.results.graph.DomainResult;
4242
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
43-
import org.hibernate.sql.results.internal.RowTransformerDatabaseSnapshotImpl;
43+
import org.hibernate.sql.results.internal.RowTransformerArrayImpl;
4444
import org.hibernate.sql.results.spi.ListResultsConsumer;
4545
import org.hibernate.type.BasicType;
4646
import org.hibernate.type.StandardBasicTypes;
@@ -176,7 +176,7 @@ Object[] loadDatabaseSnapshot(Object id, SharedSessionContractImplementor sessio
176176
jdbcSelect,
177177
jdbcParameterBindings,
178178
new BaseExecutionContext( session ),
179-
RowTransformerDatabaseSnapshotImpl.instance(),
179+
RowTransformerArrayImpl.instance(),
180180
null,
181181
ListResultsConsumer.UniqueSemantic.FILTER,
182182
1

hibernate-core/src/main/java/org/hibernate/loader/ast/internal/SingleIdArrayLoadPlan.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,13 @@
66
*/
77
package org.hibernate.loader.ast.internal;
88

9-
import java.util.List;
10-
119
import org.hibernate.LockOptions;
1210
import org.hibernate.engine.spi.SessionFactoryImplementor;
1311
import org.hibernate.metamodel.mapping.EntityMappingType;
1412
import org.hibernate.metamodel.mapping.ModelPart;
15-
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
1613
import org.hibernate.sql.ast.tree.select.SelectStatement;
1714
import org.hibernate.sql.exec.spi.JdbcParametersList;
18-
import org.hibernate.sql.results.internal.RowTransformerDatabaseSnapshotImpl;
15+
import org.hibernate.sql.results.internal.RowTransformerArrayImpl;
1916
import org.hibernate.sql.results.spi.RowTransformer;
2017

2118
/**
@@ -37,7 +34,7 @@ public SingleIdArrayLoadPlan(
3734

3835
@Override
3936
protected RowTransformer<Object[]> getRowTransformer() {
40-
return RowTransformerDatabaseSnapshotImpl.instance();
37+
return RowTransformerArrayImpl.instance();
4138
}
4239

4340
}

hibernate-core/src/main/java/org/hibernate/sql/results/internal/LoadingCollectionEntryImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public <T> void load(T arg1, BiConsumer<T, List<Object>> loadingEntryConsumer) {
8282

8383
final boolean hasNoQueuedAdds = collectionInstance.endRead();
8484
final SharedSessionContractImplementor session = executionContext.getSession();
85-
final PersistenceContext persistenceContext = session.getPersistenceContext();
85+
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
8686
final CollectionPersister collectionDescriptor = getCollectionDescriptor();
8787

8888
ResultsHelper.finalizeCollectionLoading(

hibernate-core/src/main/java/org/hibernate/sql/results/internal/RowTransformerDatabaseSnapshotImpl.java

Lines changed: 0 additions & 33 deletions
This file was deleted.

hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardRowReader.java

Lines changed: 41 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public class StandardRowReader<T> implements RowReader<T> {
3939
private final Initializer<InitializerData>[] sortedForResolveInstance;
4040
private final InitializerData[] sortedForResolveInstanceData;
4141
private final boolean hasCollectionInitializers;
42-
private final RowTransformer<T> rowTransformer;
42+
private final @Nullable RowTransformer<T> rowTransformer;
4343
private final Class<T> domainResultJavaType;
4444

4545
private final ComponentType componentType;
@@ -78,7 +78,11 @@ public StandardRowReader(
7878
this.sortedForResolveInstance = (Initializer<InitializerData>[]) sortedForResolveInitializers;
7979
this.sortedForResolveInstanceData = new InitializerData[sortedForResolveInstance.length];
8080
this.hasCollectionInitializers = hasCollectionInitializers;
81-
this.rowTransformer = rowTransformer;
81+
this.rowTransformer = rowTransformer == RowTransformerArrayImpl.INSTANCE && resultAssemblers.length != 1
82+
|| rowTransformer == RowTransformerStandardImpl.INSTANCE
83+
|| rowTransformer == RowTransformerSingularReturnImpl.INSTANCE && resultAssemblers.length == 1
84+
? null
85+
: rowTransformer;
8286
this.domainResultJavaType = domainResultJavaType;
8387
if ( domainResultJavaType == null
8488
|| domainResultJavaType == Object[].class
@@ -136,117 +140,90 @@ public boolean hasCollectionInitializers() {
136140
public T readRow(RowProcessingState rowProcessingState) {
137141
coordinateInitializers( rowProcessingState );
138142

143+
final T result;
144+
if ( componentType != ComponentType.OBJECT ) {
145+
result = readPrimitiveRow( rowProcessingState );
146+
}
147+
else {
148+
if ( resultAssemblers.length == 1 && rowTransformer == null ) {
149+
//noinspection unchecked
150+
result = (T) resultAssemblers[0].assemble( rowProcessingState );
151+
}
152+
else {
153+
final Object[] resultRow = (Object[]) Array.newInstance( resultElementClass, resultAssemblers.length );
154+
for ( int i = 0; i < resultAssemblers.length; i++ ) {
155+
resultRow[i] = resultAssemblers[i].assemble( rowProcessingState );
156+
}
157+
//noinspection unchecked
158+
result = rowTransformer == null
159+
? (T) resultRow
160+
: rowTransformer.transformRow( resultRow );
161+
}
162+
}
163+
164+
finishUpRow();
165+
return result;
166+
}
167+
168+
private T readPrimitiveRow(RowProcessingState rowProcessingState) {
139169
// The following is ugly, but unfortunately necessary to not hurt performance.
140170
// This implementation was micro-benchmarked and discussed with Francesco Nigro,
141171
// who hinted that using this style instead of the reflective Array.getLength(), Array.set()
142172
// is easier for the JVM to optimize
143173
switch ( componentType ) {
144174
case BOOLEAN:
145175
final boolean[] resultBooleanRow = new boolean[resultAssemblers.length];
146-
147176
for ( int i = 0; i < resultAssemblers.length; i++ ) {
148-
final DomainResultAssembler assembler = resultAssemblers[i];
149-
resultBooleanRow[i] = (boolean) assembler.assemble( rowProcessingState );
177+
resultBooleanRow[i] = (boolean) resultAssemblers[i].assemble( rowProcessingState );
150178
}
151-
152-
afterRow( rowProcessingState );
153-
154179
return (T) resultBooleanRow;
155180
case BYTE:
156181
final byte[] resultByteRow = new byte[resultAssemblers.length];
157-
158182
for ( int i = 0; i < resultAssemblers.length; i++ ) {
159-
final DomainResultAssembler assembler = resultAssemblers[i];
160-
resultByteRow[i] = (byte) assembler.assemble( rowProcessingState );
183+
resultByteRow[i] = (byte) resultAssemblers[i].assemble( rowProcessingState );
161184
}
162-
163-
afterRow( rowProcessingState );
164-
165185
return (T) resultByteRow;
166186
case CHAR:
167187
final char[] resultCharRow = new char[resultAssemblers.length];
168-
169188
for ( int i = 0; i < resultAssemblers.length; i++ ) {
170-
final DomainResultAssembler assembler = resultAssemblers[i];
171-
resultCharRow[i] = (char) assembler.assemble( rowProcessingState );
189+
resultCharRow[i] = (char) resultAssemblers[i].assemble( rowProcessingState );
172190
}
173-
174-
afterRow( rowProcessingState );
175-
176191
return (T) resultCharRow;
177192
case SHORT:
178193
final short[] resultShortRow = new short[resultAssemblers.length];
179-
180194
for ( int i = 0; i < resultAssemblers.length; i++ ) {
181-
final DomainResultAssembler assembler = resultAssemblers[i];
182-
resultShortRow[i] = (short) assembler.assemble( rowProcessingState );
195+
resultShortRow[i] = (short) resultAssemblers[i].assemble( rowProcessingState );
183196
}
184-
185-
afterRow( rowProcessingState );
186-
187197
return (T) resultShortRow;
188198
case INT:
189199
final int[] resultIntRow = new int[resultAssemblers.length];
190-
191200
for ( int i = 0; i < resultAssemblers.length; i++ ) {
192-
final DomainResultAssembler assembler = resultAssemblers[i];
193-
resultIntRow[i] = (int) assembler.assemble( rowProcessingState );
201+
resultIntRow[i] = (int) resultAssemblers[i].assemble( rowProcessingState );
194202
}
195-
196-
afterRow( rowProcessingState );
197-
198203
return (T) resultIntRow;
199204
case LONG:
200205
final long[] resultLongRow = new long[resultAssemblers.length];
201-
202206
for ( int i = 0; i < resultAssemblers.length; i++ ) {
203-
final DomainResultAssembler assembler = resultAssemblers[i];
204-
resultLongRow[i] = (long) assembler.assemble( rowProcessingState );
207+
resultLongRow[i] = (long) resultAssemblers[i].assemble( rowProcessingState );
205208
}
206-
207-
afterRow( rowProcessingState );
208-
209209
return (T) resultLongRow;
210210
case FLOAT:
211211
final float[] resultFloatRow = new float[resultAssemblers.length];
212-
213212
for ( int i = 0; i < resultAssemblers.length; i++ ) {
214-
final DomainResultAssembler assembler = resultAssemblers[i];
215-
resultFloatRow[i] = (float) assembler.assemble( rowProcessingState );
213+
resultFloatRow[i] = (float) resultAssemblers[i].assemble( rowProcessingState );
216214
}
217-
218-
afterRow( rowProcessingState );
219-
220215
return (T) resultFloatRow;
221216
case DOUBLE:
222217
final double[] resultDoubleRow = new double[resultAssemblers.length];
223-
224218
for ( int i = 0; i < resultAssemblers.length; i++ ) {
225-
final DomainResultAssembler assembler = resultAssemblers[i];
226-
resultDoubleRow[i] = (double) assembler.assemble( rowProcessingState );
219+
resultDoubleRow[i] = (double) resultAssemblers[i].assemble( rowProcessingState );
227220
}
228-
229-
afterRow( rowProcessingState );
230-
231221
return (T) resultDoubleRow;
232222
default:
233-
final Object[] resultRow = (Object[]) Array.newInstance( resultElementClass, resultAssemblers.length );
234-
235-
for ( int i = 0; i < resultAssemblers.length; i++ ) {
236-
final DomainResultAssembler assembler = resultAssemblers[i];
237-
resultRow[i] = assembler.assemble( rowProcessingState );
238-
}
239-
240-
afterRow( rowProcessingState );
241-
242-
return rowTransformer.transformRow( resultRow );
223+
throw new AssertionError( "Object should be handled specially" );
243224
}
244225
}
245226

246-
private void afterRow(RowProcessingState rowProcessingState) {
247-
finishUpRow();
248-
}
249-
250227
private void finishUpRow() {
251228
for ( InitializerData data : initializersData ) {
252229
data.setState( Initializer.State.UNINITIALIZED );

hibernate-core/src/main/java/org/hibernate/sql/results/spi/ListResultsConsumer.java

Lines changed: 52 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ public ListResultsConsumer(UniqueSemantic uniqueSemantic) {
105105
}
106106

107107
private static class Results<R> {
108-
private final List<R> results;
108+
private final ArrayList<R> results;
109109
private final JavaType<R> resultJavaType;
110110

111111
public Results(JavaType<R> resultJavaType, int initialSize) {
@@ -188,37 +188,17 @@ public List<R> consume(
188188
results = new Results<>( domainResultJavaType, initialCollectionSize );
189189
}
190190

191-
int readRows = 0;
191+
final int readRows;
192192
if ( uniqueSemantic == UniqueSemantic.FILTER
193193
|| uniqueSemantic == UniqueSemantic.ASSERT && rowReader.hasCollectionInitializers()
194194
|| uniqueSemantic == UniqueSemantic.ALLOW && isEntityResultType ) {
195-
while ( rowProcessingState.next() ) {
196-
final boolean added = results.addUnique( rowReader.readRow( rowProcessingState ) );
197-
rowProcessingState.finishRowProcessing( added );
198-
readRows++;
199-
}
195+
readRows = readUnique( rowProcessingState, rowReader, results );
200196
}
201197
else if ( uniqueSemantic == UniqueSemantic.ASSERT ) {
202-
while ( rowProcessingState.next() ) {
203-
if ( !results.addUnique( rowReader.readRow( rowProcessingState ) ) ) {
204-
throw new HibernateException(
205-
String.format(
206-
Locale.ROOT,
207-
"Duplicate row was found and `%s` was specified",
208-
UniqueSemantic.ASSERT
209-
)
210-
);
211-
}
212-
rowProcessingState.finishRowProcessing( true );
213-
readRows++;
214-
}
198+
readRows = readUniqueAssert( rowProcessingState, rowReader, results );
215199
}
216200
else {
217-
while ( rowProcessingState.next() ) {
218-
results.add( rowReader.readRow( rowProcessingState ) );
219-
rowProcessingState.finishRowProcessing( true );
220-
readRows++;
221-
}
201+
readRows = read( rowProcessingState, rowReader, results );
222202
}
223203

224204
rowReader.finishUp( rowProcessingState );
@@ -260,6 +240,53 @@ else if ( uniqueSemantic == UniqueSemantic.ASSERT ) {
260240
throw new IllegalStateException( "Should not reach this" );
261241
}
262242

243+
private static <R> int read(
244+
RowProcessingStateStandardImpl rowProcessingState,
245+
RowReader<R> rowReader,
246+
Results<R> results) {
247+
int readRows = 0;
248+
while ( rowProcessingState.next() ) {
249+
results.add( rowReader.readRow( rowProcessingState ) );
250+
rowProcessingState.finishRowProcessing( true );
251+
readRows++;
252+
}
253+
return readRows;
254+
}
255+
256+
private static <R> int readUniqueAssert(
257+
RowProcessingStateStandardImpl rowProcessingState,
258+
RowReader<R> rowReader,
259+
Results<R> results) {
260+
int readRows = 0;
261+
while ( rowProcessingState.next() ) {
262+
if ( !results.addUnique( rowReader.readRow( rowProcessingState ) ) ) {
263+
throw new HibernateException(
264+
String.format(
265+
Locale.ROOT,
266+
"Duplicate row was found and `%s` was specified",
267+
UniqueSemantic.ASSERT
268+
)
269+
);
270+
}
271+
rowProcessingState.finishRowProcessing( true );
272+
readRows++;
273+
}
274+
return readRows;
275+
}
276+
277+
private static <R> int readUnique(
278+
RowProcessingStateStandardImpl rowProcessingState,
279+
RowReader<R> rowReader,
280+
Results<R> results) {
281+
int readRows = 0;
282+
while ( rowProcessingState.next() ) {
283+
final boolean added = results.addUnique( rowReader.readRow( rowProcessingState ) );
284+
rowProcessingState.finishRowProcessing( added );
285+
readRows++;
286+
}
287+
return readRows;
288+
}
289+
263290
private JavaType<R> resolveDomainResultJavaType(
264291
Class<R> domainResultResultJavaType,
265292
List<@Nullable JavaType<?>> resultJavaTypes,

0 commit comments

Comments
 (0)