HHH-16683 Micro optimisations for MappingMetamodelImpl.getEntityDescriptor
This commit is contained in:
parent
1d30b0161f
commit
5c60b632a1
|
@ -16,6 +16,7 @@ import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||||
import org.hibernate.metamodel.mapping.ModelPart;
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.metamodel.mapping.NonTransientException;
|
import org.hibernate.metamodel.mapping.NonTransientException;
|
||||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||||
|
import org.hibernate.metamodel.model.domain.internal.EntityPersisterConcurrentMap;
|
||||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
||||||
|
@ -33,7 +34,7 @@ public class MappingModelCreationProcess {
|
||||||
* Triggers creation of the mapping model
|
* Triggers creation of the mapping model
|
||||||
*/
|
*/
|
||||||
public static void process(
|
public static void process(
|
||||||
Map<String,EntityPersister> entityPersisterMap,
|
EntityPersisterConcurrentMap entityPersisterMap,
|
||||||
RuntimeModelCreationContext creationContext) {
|
RuntimeModelCreationContext creationContext) {
|
||||||
final MappingModelCreationProcess process = new MappingModelCreationProcess(
|
final MappingModelCreationProcess process = new MappingModelCreationProcess(
|
||||||
entityPersisterMap,
|
entityPersisterMap,
|
||||||
|
@ -42,14 +43,14 @@ public class MappingModelCreationProcess {
|
||||||
process.execute();
|
process.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Map<String,EntityPersister> entityPersisterMap;
|
private final EntityPersisterConcurrentMap entityPersisterMap;
|
||||||
private final RuntimeModelCreationContext creationContext;
|
private final RuntimeModelCreationContext creationContext;
|
||||||
|
|
||||||
private String currentlyProcessingRole;
|
private String currentlyProcessingRole;
|
||||||
private List<PostInitCallbackEntry> postInitCallbacks;
|
private List<PostInitCallbackEntry> postInitCallbacks;
|
||||||
|
|
||||||
private MappingModelCreationProcess(
|
private MappingModelCreationProcess(
|
||||||
Map<String, EntityPersister> entityPersisterMap,
|
EntityPersisterConcurrentMap entityPersisterMap,
|
||||||
RuntimeModelCreationContext creationContext) {
|
RuntimeModelCreationContext creationContext) {
|
||||||
this.entityPersisterMap = entityPersisterMap;
|
this.entityPersisterMap = entityPersisterMap;
|
||||||
this.creationContext = creationContext;
|
this.creationContext = creationContext;
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* 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.metamodel.model.domain.internal;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concurrent Map implementation of mappings entity name -> EntityPersister.
|
||||||
|
* Concurrency is optimised for read operations; write operations will
|
||||||
|
* acquire a lock and are relatively costly: only use for long living,
|
||||||
|
* read-mostly use cases.
|
||||||
|
* This implementation attempts to avoid type pollution problems.
|
||||||
|
*/
|
||||||
|
public final class EntityPersisterConcurrentMap {
|
||||||
|
|
||||||
|
private final ConcurrentHashMap<String,EntityPersisterHolder> map = new ConcurrentHashMap<>();
|
||||||
|
private volatile EntityPersister[] values = new EntityPersister[0];
|
||||||
|
private volatile String[] keys = new String[0];
|
||||||
|
|
||||||
|
public EntityPersister get(final String name) {
|
||||||
|
final EntityPersisterHolder entityPersisterHolder = map.get( name );
|
||||||
|
if ( entityPersisterHolder != null ) {
|
||||||
|
return entityPersisterHolder.entityPersister;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityPersister[] values() {
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void put(final String name, final EntityPersister entityPersister) {
|
||||||
|
map.put( name, new EntityPersisterHolder( entityPersister ) );
|
||||||
|
recomputeValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void putIfAbsent(final String name, final EntityPersister entityPersister) {
|
||||||
|
map.putIfAbsent( name, new EntityPersisterHolder( entityPersister ) );
|
||||||
|
recomputeValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsKey(final String name) {
|
||||||
|
return map.containsKey( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] keys() {
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void recomputeValues() {
|
||||||
|
//Assumption: the write lock is being held (synchronize on this)
|
||||||
|
final int size = map.size();
|
||||||
|
final EntityPersister[] newValues = new EntityPersister[size];
|
||||||
|
final String[] newKeys = new String[size];
|
||||||
|
int i = 0;
|
||||||
|
for ( Map.Entry<String, EntityPersisterHolder> e : map.entrySet() ) {
|
||||||
|
newValues[i] = e.getValue().entityPersister;
|
||||||
|
newKeys[i] = e.getKey();
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
this.values = newValues;
|
||||||
|
this.keys = newKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Higly inefficient - do not use; this exists
|
||||||
|
* to support other deprecated methods and will be removed.
|
||||||
|
*/
|
||||||
|
@Deprecated(forRemoval = true)
|
||||||
|
public Map<String, EntityPersister> convertToMap() {
|
||||||
|
return map.entrySet().stream().collect( Collectors.toUnmodifiableMap(
|
||||||
|
Map.Entry::getKey,
|
||||||
|
e -> e.getValue().entityPersister
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation note: since EntityPersister is an highly used
|
||||||
|
* interface, we intentionally avoid using a generic Map referring
|
||||||
|
* to it to avoid type pollution.
|
||||||
|
* Using a concrete holder class bypasses the problem, at a minimal
|
||||||
|
* tradeoff of memory.
|
||||||
|
*/
|
||||||
|
private final static class EntityPersisterHolder {
|
||||||
|
|
||||||
|
private final EntityPersister entityPersister;
|
||||||
|
|
||||||
|
EntityPersisterHolder(final EntityPersister entityPersister) {
|
||||||
|
Objects.requireNonNull( entityPersister );
|
||||||
|
this.entityPersister = entityPersister;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -115,7 +115,7 @@ public class MappingMetamodelImpl extends QueryParameterBindingTypeResolverImpl
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// RuntimeModel
|
// RuntimeModel
|
||||||
|
|
||||||
private final Map<String, EntityPersister> entityPersisterMap = new ConcurrentHashMap<>();
|
private final EntityPersisterConcurrentMap entityPersisterMap = new EntityPersisterConcurrentMap();
|
||||||
private final Map<String, CollectionPersister> collectionPersisterMap = new ConcurrentHashMap<>();
|
private final Map<String, CollectionPersister> collectionPersisterMap = new ConcurrentHashMap<>();
|
||||||
private final Map<String, Set<String>> collectionRolesByEntityParticipant = new ConcurrentHashMap<>();
|
private final Map<String, Set<String>> collectionRolesByEntityParticipant = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@ -375,12 +375,14 @@ public class MappingMetamodelImpl extends QueryParameterBindingTypeResolverImpl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void forEachEntityDescriptor(Consumer<EntityPersister> action) {
|
public void forEachEntityDescriptor(Consumer<EntityPersister> action) {
|
||||||
entityPersisterMap.values().forEach( action );
|
for ( EntityPersister value : entityPersisterMap.values() ) {
|
||||||
|
action.accept( value );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stream<EntityPersister> streamEntityDescriptors() {
|
public Stream<EntityPersister> streamEntityDescriptors() {
|
||||||
return entityPersisterMap.values().stream();
|
return Arrays.stream( entityPersisterMap.values() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -547,7 +549,7 @@ public class MappingMetamodelImpl extends QueryParameterBindingTypeResolverImpl
|
||||||
|
|
||||||
@Override @SuppressWarnings("deprecation")
|
@Override @SuppressWarnings("deprecation")
|
||||||
public Map<String, EntityPersister> entityPersisters() {
|
public Map<String, EntityPersister> entityPersisters() {
|
||||||
return entityPersisterMap;
|
return entityPersisterMap.convertToMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override @SuppressWarnings("deprecation")
|
@Override @SuppressWarnings("deprecation")
|
||||||
|
@ -634,7 +636,7 @@ public class MappingMetamodelImpl extends QueryParameterBindingTypeResolverImpl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getAllEntityNames() {
|
public String[] getAllEntityNames() {
|
||||||
return ArrayHelper.toStringArray( entityPersisterMap.keySet() );
|
return entityPersisterMap.keys();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue