Skip to content

Using Interface-Based Projections Requires a Lot of Heap Memory #2831

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

Closed
i8r opened this issue May 16, 2023 · 3 comments
Closed

Using Interface-Based Projections Requires a Lot of Heap Memory #2831

i8r opened this issue May 16, 2023 · 3 comments
Assignees
Labels
type: bug A general bug

Comments

@i8r
Copy link

i8r commented May 16, 2023

When using the feature of interface-based projection the amount of memory that is required is significant. This has been causing issues in production system in our services that have not been able to serve records with more 2 GB of heap even though the actual payload was estimated in the order of magnitude of 10 MB.

I have build a minimal working example to illustrate the issue. It's using:

  • org.springframework.boot:spring-boot-starter-data-jpa:3.06
  • openjdk Temurin-18.0.2.1+1

The example saves 100k entities in a H2 in-memory database (the same pattern can be observed when using e.g. postgres). Then it reads the ids of those entities 1) using an interface-based projection or 2) just plain Longs. While it is expected that the second representation is smaller than the first one the difference seems too big to be acceptable:

image

Steps

@i8r i8r changed the title Using Interface-Based Projections Use a Lot Of Heap Memory Using Interface-Based Projections Requires a Lot of Heap Memory May 16, 2023
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label May 16, 2023
@mp911de mp911de self-assigned this May 16, 2023
@mp911de
Copy link
Member

mp911de commented May 16, 2023

Thanks for bringing this to our attention.

Projections are associated with an invocation handler and a backing object at least which requires much more memory than a plain long value.

We will have a look into our infrastructure and whether we can optimize our projection support.

@mp911de mp911de transferred this issue from spring-projects/spring-data-jpa May 16, 2023
@mp911de mp911de added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels May 16, 2023
@mp911de
Copy link
Member

mp911de commented May 16, 2023

We have indeed quite an increased memory usage profile due to the recreation of DefaultMethodInvokingMethodInterceptor that holds internally a method cache.

I tweaked your example to 400.000 proxy objects resulting in about 1500MB of memory usage. After caching the DefaultMethodInvokingMethodInterceptor instance, we can get down to 320MB.

Spring Framework internally applies several recomputations therefore bulk creation can quickly get costly due to the allocation of various objects. Let me see whether there's additional potential for optimization (roughly another 20-30MB)

@i8r
Copy link
Author

i8r commented May 17, 2023

Thank you for looking into this!

I tweaked your example to 400.000 proxy objects resulting in about 1500MB of memory usage. After caching the DefaultMethodInvokingMethodInterceptor instance, we can get down to 320MB.

That's a good improvement! Still, using almost 1 KB to represent something as small as a Long is rather wasteful but much better than using 4 KB 🎉

@mp911de mp911de added this to the 2.7.13 (2021.2.13) milestone May 17, 2023
mp911de added a commit that referenced this issue May 17, 2023
We now reduce allocations of DefaultMethodInvokingMethodInterceptor by reusing DefaultMethodInvokingMethodInterceptor within a ProxyProjectionFactory. We also reduced allocations during default method discovery and reuse the default methods information within the projection information cache.

Closes #2831
mp911de added a commit that referenced this issue May 17, 2023
We now reduce allocations of DefaultMethodInvokingMethodInterceptor by reusing DefaultMethodInvokingMethodInterceptor within a ProxyProjectionFactory. We also reduced allocations during default method discovery and reuse the default methods information within the projection information cache.

Closes #2831
mp911de added a commit that referenced this issue May 17, 2023
We now reduce allocations of DefaultMethodInvokingMethodInterceptor by reusing DefaultMethodInvokingMethodInterceptor within a ProxyProjectionFactory. We also reduced allocations during default method discovery and reuse the default methods information within the projection information cache.

Closes #2831
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

3 participants