Skip to content

Conversation

@Sanne
Copy link
Member

@Sanne Sanne commented Jun 23, 2025

https://hibernate.atlassian.net/browse/HHH-19536

Exploring some internal refactoring of how two core interceptors are being initialized:

  • EnhancementAsProxyLazinessInterceptor
  • LazyAttributeLoadingInterceptor

(These two are both implementors of of AbstractInterceptor, and represent the full set of its implementors )

The goal is to both reduce allocation pressure significantly, and also reduce the amount of repeating work being done when each of these instances is being initialized. Generally speaking, we identified a significant amount of "state" which is immutable and could be shared across all such interceptor instances when they belong to the same type.

JOL provided stats, assuming 15+ JDK, COOPS, CCPS :

Before:

org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor object internals:
OFF  SZ                               TYPE DESCRIPTION                                                      VALUE
  0   8                                    (object header: mark)                                            N/A
  8   4                                    (object header: class)                                           N/A
 12   1                            boolean AbstractInterceptor.allowLoadOutsideTransaction                  N/A
 13   1                            boolean EnhancementAsProxyLazinessInterceptor.inLineDirtyChecking        N/A
 14   1                            boolean EnhancementAsProxyLazinessInterceptor.initializeBeforeWrite      N/A
 15   1                                    (alignment/padding gap)                                          
 16   4                             String AbstractInterceptor.entityName                                   N/A
 20   4   SharedSessionContractImplementor AbstractInterceptor.session                                      N/A
 24   4                             String AbstractInterceptor.sessionFactoryUuid                           N/A
 28   4                        Set<String> EnhancementAsProxyLazinessInterceptor.identifierAttributeNames   N/A
 32   4                      CompositeType EnhancementAsProxyLazinessInterceptor.nonAggregatedCidMapper     N/A
 36   4                          EntityKey EnhancementAsProxyLazinessInterceptor.entityKey                  N/A
 40   4                        Set<String> EnhancementAsProxyLazinessInterceptor.writtenFieldNames          N/A
 44   4                        Set<String> EnhancementAsProxyLazinessInterceptor.collectionAttributeNames   N/A
 48   4                             Status EnhancementAsProxyLazinessInterceptor.status                     N/A
 52   4                                    (object alignment gap)                                           
Instance size: 56 bytes
Space losses: 1 bytes internal + 4 bytes external = 5 bytes total

org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor object internals:
OFF  SZ                               TYPE DESCRIPTION                                             VALUE
  0   8                                    (object header: mark)                                   N/A
  8   4                                    (object header: class)                                  N/A
 12   1                            boolean AbstractInterceptor.allowLoadOutsideTransaction         N/A
 13   3                                    (alignment/padding gap)                                 
 16   4                             String AbstractInterceptor.entityName                          N/A
 20   4   SharedSessionContractImplementor AbstractInterceptor.session                             N/A
 24   4                             String AbstractInterceptor.sessionFactoryUuid                  N/A
 28   4                             Object LazyAttributeLoadingInterceptor.identifier              N/A
 32   4                        Set<String> LazyAttributeLoadingInterceptor.lazyFields              N/A
 36   4                        Set<String> LazyAttributeLoadingInterceptor.initializedLazyFields   N/A
 40   4                        Set<String> LazyAttributeLoadingInterceptor.mutableLazyFields       N/A
 44   4                                    (object alignment gap)                                  
Instance size: 48 bytes
Space losses: 3 bytes internal + 4 bytes external = 7 bytes total

After:

org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor object internals:
OFF  SZ                        TYPE DESCRIPTION                                               VALUE
  0   8                             (object header: mark)                                     N/A
  8   4                             (object header: class)                                    N/A
 12   4   SessionAssociationMarkers AbstractInterceptor.sessionAssociation                    N/A
 16   4                   EntityKey EnhancementAsProxyLazinessInterceptor.entityKey           N/A
 20   4          EntityRelatedState EnhancementAsProxyLazinessInterceptor.meta                N/A
 24   4                 Set<String> EnhancementAsProxyLazinessInterceptor.writtenFieldNames   N/A
 28   4                      Status EnhancementAsProxyLazinessInterceptor.status              N/A
Instance size: 32 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total


org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor object internals:
OFF  SZ                        TYPE DESCRIPTION                                             VALUE
  0   8                             (object header: mark)                                   N/A
  8   4                             (object header: class)                                  N/A
 12   4   SessionAssociationMarkers AbstractInterceptor.sessionAssociation                  N/A
 16   4                      Object LazyAttributeLoadingInterceptor.identifier              N/A
 20   4          EntityRelatedState LazyAttributeLoadingInterceptor.entityMeta              N/A
 24   4                 Set<String> LazyAttributeLoadingInterceptor.initializedLazyFields   N/A
 28   4                             (object alignment gap)                                  
Instance size: 32 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

This exploration also led to rethink how we model the association of such an interceptor to the current Session, also providing both memory and computational benefits. Code comments hopefully explain this in more detail.

(fully relies on all existing tests)


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license
and can be relicensed under the terms of the LGPL v2.1 license in the future at the maintainers' discretion.
For more information on licensing, please check here.


https://hibernate.atlassian.net/browse/HHH-19536

@hibernate-github-bot
Copy link

hibernate-github-bot bot commented Jun 23, 2025

Thanks for your pull request!

This pull request does not follow the contribution rules. Could you have a look?

❌ All commit messages should start with a JIRA issue key matching pattern HHH-\d+
    ↳ Offending commits: [2349f78, 8519a3a]

› This message was automatically generated.

@Sanne Sanne force-pushed the LighterInterceptors branch 3 times, most recently from 2758cb3 to bcdd784 Compare June 26, 2025 21:09
@Sanne Sanne changed the title [Draft ] Lighter interceptors: more efficient initialization and lower memory usage Lighter interceptors: more efficient initialization and lower memory usage Jun 26, 2025
@Sanne Sanne force-pushed the LighterInterceptors branch from bcdd784 to 4c3ea69 Compare June 26, 2025 22:04
@Sanne Sanne merged commit d523158 into hibernate:main Jun 27, 2025
25 of 26 checks passed
@Sanne Sanne deleted the LighterInterceptors branch June 27, 2025 08:31
@Sanne Sanne restored the LighterInterceptors branch June 30, 2025 14:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant