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

Avoid wasted memory on empty maps and sets #29742

Conversation

Dunemaster
Copy link

Empty LinkedHashMaps waste quite a lot of memory (250kb) for a medium size project

The PR introduces a simple fix

A screen from yourkit profiler:

image

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Dec 26, 2022
@Dunemaster Dunemaster force-pushed the optimizeAnnotationMemoryFootprint branch from 8aa642e to f41d348 Compare December 26, 2022 09:44
@sbrannen sbrannen added in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Dec 26, 2022
@sbrannen sbrannen added this to the 6.0.4 milestone Dec 26, 2022
@sbrannen sbrannen self-assigned this Dec 26, 2022
@jhoeller
Copy link
Contributor

jhoeller commented Jan 6, 2023

Any specific reason to use Set/Map.of() over Collections.emptySet/Map()? The latter seems even more efficient implementation-wise.

@jhoeller jhoeller self-assigned this Jan 6, 2023
@Dunemaster
Copy link
Author

Dunemaster commented Jan 6, 2023

Any specific reason to use Set/Map.of() over Collections.emptySet/Map()? The latter seems even more efficient implementation-wise.

Would you be so kind to explain the difference? Both methods return a static instance of an empty map/set.

I used Set/Map.of() for the sake of brevity, and do not see any performance benefit in using either Set/Map.of() or Collections.emptySet/Map()

@vlsi
Copy link
Contributor

vlsi commented Jan 6, 2023

The difference between Map.of and Collections.emptyMap is that Map.of().contains(null) would throw exception while Collections.emptyMap().contains(null) would return false.

See https://stackoverflow.com/a/46406203/1261287

@Dunemaster
Copy link
Author

The difference between Map.of and Collections.emptyMap is that Map.of().contains(null) would throw exception while Collections.emptyMap().contains(null) would return false.

See https://stackoverflow.com/a/46406203/1261287

wow, thanks.
I will change to Collections.emptyMap, if you think that is better

@jhoeller
Copy link
Contributor

jhoeller commented Jan 9, 2023

Aside from the contains(null) benefit, the footprint of Collections.emptySet/Map() should also be slightly better since those implementations are actually designed for emptiness (not just initialized without any elements as with Set/Map.of()).

@vlsi
Copy link
Contributor

vlsi commented Jan 9, 2023

Can you elaborate?

AFAIK Map.of returns a static instance that is optimised for empty case: https://github.com/openjdk/jdk/blob/679e485838881c1364845072af305fb60d95e60a/src/java.base/share/classes/java/util/Map.java#L1333

@Dunemaster
Copy link
Author

Replaced Set.of() and Map.of with Collections.emptyXXX in order to avoid possible compatibility breaks

@Dunemaster Dunemaster requested review from vlsi and mjd507 and removed request for vlsi and mjd507 January 10, 2023 14:52
@Dunemaster Dunemaster requested review from mjd507 and removed request for vlsi January 10, 2023 14:52
@sbrannen sbrannen changed the title Do not waste memory on empty hash maps in annotations Avoid wasted memory on empty maps and sets Jan 10, 2023
Copy link
Contributor

@vlsi vlsi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks.

Frankly speaking, I incline that adding early return in checkConfigMembers would make the code slightly easier to follow.

Copy link

@mjd507 mjd507 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good for me (I’m just not quite sure about the impact of the code changes from high level, so let someone else to review and approve)

@sbrannen sbrannen closed this in 3738a45 Jan 10, 2023
@sbrannen
Copy link
Member

This has been merged into main in 3738a45 and revised in d5fb5d0.

Thanks

@Dunemaster
Copy link
Author

Should this change be ported to 5.3?

@sbrannen
Copy link
Member

Should this change be ported to 5.3?

We do not intend to backport minor enhancements such as this to 5.3.x.

mdeinum pushed a commit to mdeinum/spring-framework that referenced this pull request Jun 29, 2023
This commit avoids wasted memory on empty hash maps in
MergedAnnotationReadingVisitor and empty sets in InjectionMetadata.

Closes spring-projectsgh-29742
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants