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.NonTransientException;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.metamodel.model.domain.internal.EntityPersisterConcurrentMap;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
||||
|
@ -33,7 +34,7 @@ public class MappingModelCreationProcess {
|
|||
* Triggers creation of the mapping model
|
||||
*/
|
||||
public static void process(
|
||||
Map<String,EntityPersister> entityPersisterMap,
|
||||
EntityPersisterConcurrentMap entityPersisterMap,
|
||||
RuntimeModelCreationContext creationContext) {
|
||||
final MappingModelCreationProcess process = new MappingModelCreationProcess(
|
||||
entityPersisterMap,
|
||||
|
@ -42,14 +43,14 @@ public class MappingModelCreationProcess {
|
|||
process.execute();
|
||||
}
|
||||
|
||||
private final Map<String,EntityPersister> entityPersisterMap;
|
||||
private final EntityPersisterConcurrentMap entityPersisterMap;
|
||||
private final RuntimeModelCreationContext creationContext;
|
||||
|
||||
private String currentlyProcessingRole;
|
||||
private List<PostInitCallbackEntry> postInitCallbacks;
|
||||
|
||||
private MappingModelCreationProcess(
|
||||
Map<String, EntityPersister> entityPersisterMap,
|
||||
EntityPersisterConcurrentMap entityPersisterMap,
|
||||
RuntimeModelCreationContext creationContext) {
|
||||
this.entityPersisterMap = entityPersisterMap;
|
||||
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
|
||||
|
||||
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, Set<String>> collectionRolesByEntityParticipant = new ConcurrentHashMap<>();
|
||||
|
||||
|
@ -375,12 +375,14 @@ public class MappingMetamodelImpl extends QueryParameterBindingTypeResolverImpl
|
|||
|
||||
@Override
|
||||
public void forEachEntityDescriptor(Consumer<EntityPersister> action) {
|
||||
entityPersisterMap.values().forEach( action );
|
||||
for ( EntityPersister value : entityPersisterMap.values() ) {
|
||||
action.accept( value );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<EntityPersister> streamEntityDescriptors() {
|
||||
return entityPersisterMap.values().stream();
|
||||
return Arrays.stream( entityPersisterMap.values() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -547,7 +549,7 @@ public class MappingMetamodelImpl extends QueryParameterBindingTypeResolverImpl
|
|||
|
||||
@Override @SuppressWarnings("deprecation")
|
||||
public Map<String, EntityPersister> entityPersisters() {
|
||||
return entityPersisterMap;
|
||||
return entityPersisterMap.convertToMap();
|
||||
}
|
||||
|
||||
@Override @SuppressWarnings("deprecation")
|
||||
|
@ -634,7 +636,7 @@ public class MappingMetamodelImpl extends QueryParameterBindingTypeResolverImpl
|
|||
|
||||
@Override
|
||||
public String[] getAllEntityNames() {
|
||||
return ArrayHelper.toStringArray( entityPersisterMap.keySet() );
|
||||
return entityPersisterMap.keys();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue