(perf) fix cases of Map resizing when number of entries known ahead of time;

(perf) convert some List Iterators to "for i" loops
This commit is contained in:
Steve Ebersole 2019-10-16 13:48:23 -05:00
parent 5482c55e6c
commit 1a3fcff8af
17 changed files with 120 additions and 53 deletions

View File

@ -716,8 +716,9 @@ public abstract class SimpleValue implements KeyValue {
@Override
public boolean hasAnyInsertableColumns() {
for ( Boolean val : insertability ) {
if ( val ) {
//noinspection ForLoopReplaceableByForEach
for ( int i = 0; i < insertability.size(); i++ ) {
if ( insertability.get( i ) ) {
return true;
}
}
@ -732,8 +733,8 @@ public abstract class SimpleValue implements KeyValue {
@Override
public boolean hasAnyUpdatableColumns() {
for ( Boolean val : updatability ) {
if ( val ) {
for ( int i = 0; i < updatability.size(); i++ ) {
if ( updatability.get( i ) ) {
return true;
}
}

View File

@ -16,9 +16,9 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
public class OptimizedPojoInstantiatorImpl<J> extends AbstractPojoInstantiator {
private final ReflectionOptimizer.InstantiationOptimizer instantiationOptimizer;
public OptimizedPojoInstantiatorImpl(JavaTypeDescriptor javaTypeDescriptor, ReflectionOptimizer reflectionOptimizer) {
public OptimizedPojoInstantiatorImpl(JavaTypeDescriptor javaTypeDescriptor, ReflectionOptimizer.InstantiationOptimizer instantiationOptimizer) {
super( javaTypeDescriptor.getJavaType() );
this.instantiationOptimizer = reflectionOptimizer.getInstantiationOptimizer();
this.instantiationOptimizer = instantiationOptimizer;
}
@Override

View File

@ -38,6 +38,7 @@ public class StandardPojoEmbeddableRepresentationStrategy extends AbstractEmbedd
public StandardPojoEmbeddableRepresentationStrategy(
Component bootDescriptor,
RuntimeModelCreationContext creationContext) {
//noinspection unchecked
super(
bootDescriptor,
creationContext.getTypeConfiguration()
@ -55,7 +56,10 @@ public class StandardPojoEmbeddableRepresentationStrategy extends AbstractEmbedd
this.reflectionOptimizer = buildReflectionOptimizer( bootDescriptor, creationContext );
if ( reflectionOptimizer != null && reflectionOptimizer.getInstantiationOptimizer() != null ) {
this.instantiator = new OptimizedPojoInstantiatorImpl<>( getEmbeddableJavaTypeDescriptor(), reflectionOptimizer );
final ReflectionOptimizer.InstantiationOptimizer instantiationOptimizer = reflectionOptimizer.getInstantiationOptimizer();
this.instantiator = instantiationOptimizer != null
? new OptimizedPojoInstantiatorImpl<>( getEmbeddableJavaTypeDescriptor(), instantiationOptimizer )
: new PojoInstantiatorImpl<>( getEmbeddableJavaTypeDescriptor() );
}
else {
this.instantiator = new PojoInstantiatorImpl<>( getEmbeddableJavaTypeDescriptor() );

View File

@ -108,10 +108,16 @@ public class StandardPojoEntityRepresentationStrategy implements EntityRepresent
this.proxyFactory = createProxyFactory( bootDescriptor, bytecodeProvider, creationContext );
this.reflectionOptimizer = resolveReflectionOptimizer( bootDescriptor, bytecodeProvider );
this.reflectionOptimizer = resolveReflectionOptimizer( bootDescriptor, bytecodeProvider, sessionFactory );
if ( reflectionOptimizer != null && reflectionOptimizer.getInstantiationOptimizer() != null ) {
this.instantiator = new OptimizedPojoInstantiatorImpl<>( mappedJtd, reflectionOptimizer );
if ( reflectionOptimizer != null ) {
final ReflectionOptimizer.InstantiationOptimizer instantiationOptimizer = reflectionOptimizer.getInstantiationOptimizer();
if ( instantiationOptimizer != null ) {
this.instantiator = new OptimizedPojoInstantiatorImpl<>( mappedJtd, instantiationOptimizer );
}
else {
this.instantiator = new PojoInstantiatorImpl<>( mappedJtd );
}
}
else {
this.instantiator = new PojoInstantiatorImpl<>( mappedJtd );
@ -226,7 +232,8 @@ public class StandardPojoEntityRepresentationStrategy implements EntityRepresent
private ReflectionOptimizer resolveReflectionOptimizer(
PersistentClass bootType,
BytecodeProvider bytecodeProvider) {
BytecodeProvider bytecodeProvider,
@SuppressWarnings("unused") SessionFactoryImplementor sessionFactory) {
final Class javaTypeToReflect;
if ( proxyFactory != null ) {
assert proxyJtd != null;

View File

@ -27,6 +27,16 @@ public class QueryInterpretationCacheDisabledImpl implements QueryInterpretation
*/
public static final QueryInterpretationCacheDisabledImpl INSTANCE = new QueryInterpretationCacheDisabledImpl();
@Override
public int getNumberOfCachedHqlInterpretations() {
return 0;
}
@Override
public int getNumberOfCachedQueryPlans() {
return 0;
}
@Override
public SelectQueryPlan resolveSelectQueryPlan(Key key, Supplier<SelectQueryPlan> creator) {
return null;

View File

@ -61,6 +61,16 @@ public class QueryInterpretationCacheStandardImpl implements QueryInterpretation
nativeQueryParamCache = new BoundedConcurrentHashMap<>( maxQueryPlanCount, 20, BoundedConcurrentHashMap.Eviction.LIRS );
}
@Override
public int getNumberOfCachedHqlInterpretations() {
return hqlInterpretationCache.size();
}
@Override
public int getNumberOfCachedQueryPlans() {
return queryPlanCache.size();
}
@Override
public SelectQueryPlan resolveSelectQueryPlan(
Key key,

View File

@ -11,6 +11,6 @@ import org.hibernate.sql.exec.spi.ExecutionContext;
/**
* @author Steve Ebersole
*/
public interface NonSelectQueryPlan {
public interface NonSelectQueryPlan extends QueryPlan {
int executeUpdate(ExecutionContext executionContext);
}

View File

@ -23,16 +23,16 @@ public interface QueryInterpretationCache {
interface Key {
}
int getNumberOfCachedHqlInterpretations();
int getNumberOfCachedQueryPlans();
HqlInterpretation resolveHqlInterpretation(String queryString, Function<String, SqmStatement<?>> creator);
SelectQueryPlan resolveSelectQueryPlan(Key key, Supplier<SelectQueryPlan> creator);
NonSelectQueryPlan getNonSelectQueryPlan(Key key);
void cacheNonSelectQueryPlan(Key key, NonSelectQueryPlan plan);
/**
* todo (6.0) : Doesn't holding these separate from the QueryPlans lead to extra, unnecessary memory use?
*/
HqlInterpretation resolveHqlInterpretation(String queryString, Function<String, SqmStatement<?>> creator);
ParameterInterpretation resolveNativeQueryParameters(String queryString, Function<String, ParameterInterpretation> creator);
boolean isEnabled();

View File

@ -43,9 +43,11 @@ public class SqmInterpretationsKey implements QueryInterpretationCache.Key {
@SuppressWarnings("RedundantIfStatement")
private static boolean isCacheable(QuerySqmImpl<?> query) {
if ( query.getQueryOptions().getAppliedGraph() != null ) {
assert query.getQueryOptions().getAppliedGraph() != null;
if ( query.getQueryOptions().getAppliedGraph().getSemantic() != null ) {
// At the moment we cannot cache query plan if there is an
// EntityGraph involved.
// EntityGraph enabled.
return false;
}

View File

@ -8,11 +8,10 @@ package org.hibernate.sql.exec.internal;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.query.sqm.internal.DomainParameterXref;
import org.hibernate.sql.exec.spi.JdbcParameter;
import org.hibernate.sql.exec.spi.JdbcParameterBinding;
@ -28,14 +27,14 @@ public class JdbcParameterBindingsImpl implements JdbcParameterBindings {
public JdbcParameterBindingsImpl(DomainParameterXref domainParameterXref) {
if ( domainParameterXref.getSqmParameterCount() > 0 ) {
bindingMap = CollectionHelper.mapOfSize( domainParameterXref.getSqmParameterCount() );
bindingMap = new IdentityHashMap<>( domainParameterXref.getSqmParameterCount() );
}
}
@Override
public void addBinding(JdbcParameter parameter, JdbcParameterBinding binding) {
if ( bindingMap == null ) {
bindingMap = new HashMap<>();
bindingMap = new IdentityHashMap<>();
}
bindingMap.put( parameter, binding );

View File

@ -7,16 +7,13 @@
package org.hibernate.sql.results.internal;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.loader.plan.spi.EntityFetch;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.exec.spi.Callback;
import org.hibernate.sql.exec.spi.DomainParameterBindingContext;
import org.hibernate.sql.results.spi.Initializer;
@ -32,11 +29,12 @@ import org.jboss.logging.Logger;
*/
public class RowProcessingStateStandardImpl implements RowProcessingState {
private static final Logger log = Logger.getLogger( RowProcessingStateStandardImpl.class );
private static final Initializer[] NO_INITIALIZERS = new Initializer[0];
private final JdbcValuesSourceProcessingStateStandardImpl resultSetProcessingState;
private final QueryOptions queryOptions;
private final Map<NavigablePath, Initializer> initializerMap;
private final Initializer[] initializers;
private final JdbcValues jdbcValues;
private Object[] currentRowJdbcValues;
@ -52,14 +50,11 @@ public class RowProcessingStateStandardImpl implements RowProcessingState {
final List<Initializer> initializers = rowReader.getInitializers();
if ( initializers == null || initializers.isEmpty() ) {
initializerMap = null;
this.initializers = NO_INITIALIZERS;
}
else {
initializerMap = new HashMap<>();
for ( Initializer initializer : initializers ) {
initializerMap.put( initializer.getNavigablePath(), initializer );
}
//noinspection ToArrayCallWithZeroLengthArrayArgument
this.initializers = initializers.toArray( new Initializer[initializers.size()] );
}
}
@ -115,6 +110,12 @@ public class RowProcessingStateStandardImpl implements RowProcessingState {
@Override
public Initializer resolveInitializer(NavigablePath path) {
return initializerMap == null ? null : initializerMap.get( path );
for ( Initializer initializer : initializers ) {
if ( initializer.getNavigablePath().equals( path ) ) {
return initializer;
}
}
return null;
}
}

View File

@ -48,8 +48,9 @@ public class StandardJdbcValuesMapping implements JdbcValuesMapping {
AssemblerCreationState creationState) {
final List<DomainResultAssembler> assemblers = CollectionHelper.arrayList( domainResults.size() );
for ( DomainResult domainResult : domainResults ) {
final DomainResultAssembler resultAssembler = domainResult.createResultAssembler(
//noinspection ForLoopReplaceableByForEach
for ( int i = 0; i < domainResults.size(); i++ ) {
final DomainResultAssembler resultAssembler = domainResults.get( i ).createResultAssembler(
initializerConsumer,
creationState
);

View File

@ -6,11 +6,10 @@
*/
package org.hibernate.sql.results.internal.domain.composite;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.function.Consumer;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
import org.hibernate.metamodel.mapping.StateArrayContributorMapping;
@ -41,6 +40,7 @@ public abstract class AbstractCompositeInitializer extends AbstractFetchParentAc
private Object compositeInstance;
@SuppressWarnings("WeakerAccess")
public AbstractCompositeInitializer(
CompositeResultMappingNode resultDescriptor,
FetchParentAccess fetchParentAccess,
@ -52,7 +52,7 @@ public abstract class AbstractCompositeInitializer extends AbstractFetchParentAc
final int numOfAttrs = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor().getNumberOfAttributeMappings();
this.resolvedValues = new Object[ numOfAttrs ];
this.assemblerMap = CollectionHelper.mapOfSize( numOfAttrs );
this.assemblerMap = new IdentityHashMap<>( numOfAttrs );
this.embeddedModelPartDescriptor.getEmbeddableTypeDescriptor().visitStateArrayContributors(
stateArrayContributor -> {
@ -73,6 +73,7 @@ public abstract class AbstractCompositeInitializer extends AbstractFetchParentAc
return embeddedModelPartDescriptor;
}
@SuppressWarnings("WeakerAccess")
public FetchParentAccess getFetchParentAccess() {
return fetchParentAccess;
}

View File

@ -9,6 +9,7 @@ package org.hibernate.sql.results.internal.domain.entity;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
@ -75,7 +76,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
private final DomainResultAssembler discriminatorAssembler;
private final DomainResultAssembler versionAssembler;
private final Map<StateArrayContributorMapping, DomainResultAssembler> assemblerMap = new HashMap<>();
private final Map<StateArrayContributorMapping, DomainResultAssembler> assemblerMap;
// per-row state
private EntityPersister concreteDescriptor;
@ -132,6 +133,8 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
this.versionAssembler = null;
}
assemblerMap = new IdentityHashMap<>( entityDescriptor.getNumberOfAttributeMappings() );
entityDescriptor.visitStateArrayContributors(
attributeMapping -> {
// todo (6.0) : somehow we need to track whether all state is loaded/resolved

View File

@ -0,0 +1,34 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.query.hql;
import org.hibernate.orm.test.metamodel.mapping.SmokeTests;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
/**
* @author Steve Ebersole
*/
@SuppressWarnings("WeakerAccess")
@DomainModel( annotatedClasses = SmokeTests.SimpleEntity.class )
@ServiceRegistry
@SessionFactory( exportSchema = true )
public class QueryPlanCachingTest {
@Test
public void testHqlTranslationCaching(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery( "select e from SimpleEntity e" ).list();
session.createQuery( "select e from SimpleEntity e" ).list();
}
);
}
}

View File

@ -9,11 +9,10 @@ package org.hibernate.orm.test.sql.exec;
import java.sql.Statement;
import java.util.List;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.Component;
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender;
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.SimpleEntity;
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.OtherEntity;
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.SimpleEntity;
import org.hibernate.query.Query;
import org.hibernate.query.spi.QueryImplementor;
@ -37,7 +36,7 @@ import static org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender.MALE;
* @author Andrea Boriero
* @author Steve Ebersole
*/
@SuppressWarnings("WeakerAccess")
@SuppressWarnings({"WeakerAccess", "DefaultAnnotationParam"})
@DomainModel(
annotatedClasses = {SimpleEntity.class, OtherEntity.class},
extraQueryImportClasses = {
@ -47,15 +46,8 @@ import static org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender.MALE;
SmokeTests.BasicSetterBasedDto.class
}
)
@ServiceRegistry(
settings = {
@ServiceRegistry.Setting(
name = AvailableSettings.HBM2DDL_AUTO,
value = "create-drop"
)
}
)
@SessionFactory
@ServiceRegistry
@SessionFactory( exportSchema = true )
public class SmokeTests {
@BeforeEach

View File

@ -24,4 +24,6 @@ hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFa
javax.persistence.validation.mode=NONE
hibernate.service.allow_crawling=false
hibernate.session.events.log=true
hibernate.hql.bulk_id_strategy.global_temporary.drop_tables=true
hibernate.hql.bulk_id_strategy.global_temporary.drop_tables=true
hibernate.bytecode.use_reflection_optimizer=true