Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HHH-18777 Performance optimization for entities-by-key hashmap access #9175

Merged
merged 1 commit into from
Oct 28, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ the following fields are used in all circumstances, and are not worth (or not su
// Loaded entity instances, by EntityKey
private HashMap<EntityKey, EntityHolderImpl> entitiesByKey;

// New entity holder cached instance
private EntityHolderImpl newEntityHolder;

// Loaded entity instances, by EntityUniqueKey
private HashMap<EntityUniqueKey, Object> entitiesByUniqueKey;

Expand Down Expand Up @@ -182,6 +185,13 @@ private Map<EntityKey, EntityHolderImpl> getOrInitializeEntitiesByKey() {
return entitiesByKey;
}

private EntityHolderImpl getOrInitializeNewHolder() {
if ( newEntityHolder == null ) {
return newEntityHolder = new EntityHolderImpl();
}
return newEntityHolder;
}

@Override
public boolean isStateless() {
return false;
Expand Down Expand Up @@ -390,8 +400,8 @@ public EntityHolder claimEntityHolderIfPossible(
JdbcValuesSourceProcessingState processingState,
EntityInitializer<?> initializer) {
final Map<EntityKey, EntityHolderImpl> entityHolderMap = getOrInitializeEntitiesByKey();
final EntityHolderImpl oldHolder = entityHolderMap.get( key );
final EntityHolderImpl holder;
EntityHolderImpl holder = getOrInitializeNewHolder().withEntity( key, key.getPersister(), entity );
final EntityHolderImpl oldHolder = entityHolderMap.putIfAbsent( key, newEntityHolder );
if ( oldHolder != null ) {
if ( entity != null ) {
assert oldHolder.entity == null || oldHolder.entity == entity;
Expand All @@ -411,7 +421,7 @@ public EntityHolder claimEntityHolderIfPossible(
holder = oldHolder;
}
else {
entityHolderMap.put( key, holder = EntityHolderImpl.forEntity( key, key.getPersister(), entity ) );
newEntityHolder = null;
}
assert holder.entityInitializer == null || holder.entityInitializer == initializer;
holder.entityInitializer = initializer;
Expand Down Expand Up @@ -494,16 +504,14 @@ public void addEntity(EntityKey key, Object entity) {
@Override
public EntityHolder addEntityHolder(EntityKey key, Object entity) {
final Map<EntityKey, EntityHolderImpl> entityHolderMap = getOrInitializeEntitiesByKey();
final EntityHolderImpl oldHolder = entityHolderMap.get( key );
final EntityHolderImpl holder;
EntityHolderImpl holder = getOrInitializeNewHolder().withEntity( key, key.getPersister(), entity );
final EntityHolderImpl oldHolder = entityHolderMap.putIfAbsent( key, holder );
if ( oldHolder != null ) {
// assert oldHolder.entity == null || oldHolder.entity == entity;
oldHolder.entity = entity;
holder = oldHolder;
}
else {
holder = EntityHolderImpl.forEntity( key, key.getPersister(), entity );
entityHolderMap.put( key, holder );
newEntityHolder = null;
}
holder.state = EntityHolderState.INITIALIZED;
final BatchFetchQueue fetchQueue = this.batchFetchQueue;
Expand Down Expand Up @@ -783,14 +791,15 @@ private void reassociateProxy(LazyInitializer li, HibernateProxy proxy) {
final EntityKey key = session.generateEntityKey( li.getInternalIdentifier(), persister );
// any earlier proxy takes precedence
final Map<EntityKey, EntityHolderImpl> entityHolderMap = getOrInitializeEntitiesByKey();
final EntityHolderImpl oldHolder = entityHolderMap.get( key );
final EntityHolderImpl holder = getOrInitializeNewHolder().withProxy( key, persister, proxy );
final EntityHolderImpl oldHolder = entityHolderMap.putIfAbsent( key, holder );
if ( oldHolder != null ) {
if ( oldHolder.proxy == null ) {
oldHolder.proxy = proxy;
}
}
else {
entityHolderMap.put( key, EntityHolderImpl.forProxy( key, persister, proxy ) );
newEntityHolder = null;
}
proxy.getHibernateLazyInitializer().setSession( session );
}
Expand Down Expand Up @@ -929,16 +938,16 @@ public Object proxyFor(EntityHolder holder, EntityPersister persister) {
@Override
public void addEnhancedProxy(EntityKey key, PersistentAttributeInterceptable entity) {
final Map<EntityKey, EntityHolderImpl> entityHolderMap = getOrInitializeEntitiesByKey();
final EntityHolderImpl oldHolder = entityHolderMap.get( key );
final EntityHolderImpl holder;
final EntityHolderImpl holder = getOrInitializeNewHolder().withEntity( key, key.getPersister(), entity );
final EntityHolderImpl oldHolder = entityHolderMap.putIfAbsent( key, holder );
if ( oldHolder != null ) {
oldHolder.entity = entity;
holder = oldHolder;
oldHolder.state = EntityHolderState.ENHANCED_PROXY;
}
else {
entityHolderMap.put( key, holder = EntityHolderImpl.forEntity( key, key.getPersister(), entity ) );
newEntityHolder = null;
holder.state = EntityHolderState.ENHANCED_PROXY;
}
holder.state = EntityHolderState.ENHANCED_PROXY;
}

@Override
Expand Down Expand Up @@ -1229,12 +1238,13 @@ public Object getProxy(EntityKey key) {
@Override
public void addProxy(EntityKey key, Object proxy) {
final Map<EntityKey, EntityHolderImpl> entityHolderMap = getOrInitializeEntitiesByKey();
final EntityHolderImpl holder = entityHolderMap.get( key );
if ( holder != null ) {
holder.proxy = proxy;
final EntityHolderImpl holder = getOrInitializeNewHolder().withProxy( key, key.getPersister(), proxy );
final EntityHolderImpl oldHolder = entityHolderMap.putIfAbsent( key, holder );
if ( oldHolder != null ) {
oldHolder.proxy = proxy;
}
else {
entityHolderMap.put( key, EntityHolderImpl.forProxy( key, key.getPersister(), proxy ) );
newEntityHolder = null;
}
}

Expand Down Expand Up @@ -1960,7 +1970,7 @@ public static StatefulPersistenceContext deserialize(
final Object entity = ois.readObject();
final Object proxy = ois.readObject();
final EntityHolderState state = (EntityHolderState) ois.readObject();
final EntityHolderImpl holder = EntityHolderImpl.forEntity( ek, persister, entity );
final EntityHolderImpl holder = new EntityHolderImpl().withEntity( ek, persister, entity );
holder.state = state;
if ( proxy != null ) {
final LazyInitializer lazyInitializer = extractLazyInitializer( proxy );
Expand Down Expand Up @@ -2177,20 +2187,15 @@ private void cleanUpInsertedKeysAfterTransaction() {
}

private static class EntityHolderImpl implements EntityHolder, Serializable {
private final EntityKey entityKey;
private final EntityPersister descriptor;
Object entity;
Object proxy;
@Nullable EntityEntry entityEntry;
EntityInitializer<?> entityInitializer;
EntityHolderState state;

private EntityHolderImpl(EntityKey entityKey, EntityPersister descriptor, Object entity, Object proxy) {
assert entityKey != null && descriptor != null;
this.entityKey = entityKey;
this.descriptor = descriptor;
this.entity = entity;
this.proxy = proxy;
private EntityKey entityKey;
private EntityPersister descriptor;
private Object entity;
private Object proxy;
private @Nullable EntityEntry entityEntry;
private EntityInitializer<?> entityInitializer;
private EntityHolderState state;

private EntityHolderImpl() {
this.state = EntityHolderState.UNINITIALIZED;
}

Expand Down Expand Up @@ -2249,12 +2254,21 @@ public boolean isDetached() {
return state == EntityHolderState.DETACHED;
}

public static EntityHolderImpl forProxy(EntityKey entityKey, EntityPersister descriptor, Object proxy) {
return new EntityHolderImpl( entityKey, descriptor, null, proxy );
public EntityHolderImpl withEntity(EntityKey entityKey, EntityPersister descriptor, Object entity) {
return withData( entityKey, descriptor, entity, null );
}

public EntityHolderImpl withProxy(EntityKey entityKey, EntityPersister descriptor, Object proxy) {
return withData( entityKey, descriptor, null, proxy );
}

public static EntityHolderImpl forEntity(EntityKey entityKey, EntityPersister descriptor, Object entity) {
return new EntityHolderImpl( entityKey, descriptor, entity, null );
public EntityHolderImpl withData(EntityKey entityKey, EntityPersister descriptor, Object entity, Object proxy) {
assert entityKey != null && descriptor != null && entityInitializer == null && state == EntityHolderState.UNINITIALIZED;
this.entityKey = entityKey;
this.descriptor = descriptor;
this.entity = entity;
this.proxy = proxy;
return this;
}
}

Expand Down
Loading