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

Perform basic property determination without java.beans.Introspector #29320

Closed
jhoeller opened this issue Oct 13, 2022 · 5 comments
Closed

Perform basic property determination without java.beans.Introspector #29320

jhoeller opened this issue Oct 13, 2022 · 5 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@jhoeller
Copy link
Contributor

Out of a discussion in #26884, we should replace our beans introspection with a basic property determination algorithm that discovers the common scenarios for Spring applications but nothing more: no indexed properties, no JDK-level customizers, etc. This significantly streamlines the discovery process on startup and allows for straightforward usage in a native image (not relying on Introspector substitutions).

The implementation that is about to be pushed for RC2 gets rid of all common java.beans.Introspector usage points in the codebase, replacing them with calls to PropertyDescriptorUtils.determineBasicProperties and StringUtils.uncapitalizeAsProperty. The entire core test suite passes with this.

Standard JavaBeans Introspector usage can be enforced through StandardBeanInfoFactory configuration in a META-INF/spring.factories file (a mechanism which existed for BeanInfo customizations before) with the following content:
org.springframework.beans.BeanInfoFactory=org.springframework.beans.StandardBeanInfoFactory
For Spring 5.3 compatible extended introspection including non-void setter methods:
org.springframework.beans.BeanInfoFactory=org.springframework.beans.ExtendedBeanInfoFactory
Neither of the two should be commonly necessary.

@jhoeller jhoeller added in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement labels Oct 13, 2022
@jhoeller jhoeller added this to the 6.0.0-RC2 milestone Oct 13, 2022
@jhoeller jhoeller self-assigned this Oct 13, 2022
@jhoeller
Copy link
Contributor Author

jhoeller commented Oct 14, 2022

Our initial experience with this is pretty compelling, both for native images and for regular JVM deployments. In microbenchmarks, the new "basic" discovery is about 10 times faster than "standard" Introspector usage when spring.beaninfo.ignore=true (the optimization flag available before) has been set - against default Introspector settings, the new algorithm is even about 16 times faster.

It's worth noting that the algorithm can be customized in 5.3 as well, using the BeanInfoFactory mechanism. Plugging in a custom SimpleBeanInfoFactory with the equivalent of our "basic" algorithm should work for 5.3 as-is, ideally ordering it before ExtendedBeanInfoFactory (the 5.3 implementation that handles non-void setter methods) since it covers that part as well.

We could potentially backport such a SimpleBeanInfoFactory as an optional variant for configuration in a custom META-INF/spring.factories file, for performance-critical scenarios where the spring.beaninfo.ignore=true property does not make enough difference. If the wider integration tests against 6.0 do not reveal problems, we could even do so for 5.3.24 already.

@dreis2211
Copy link
Contributor

dreis2211 commented Oct 14, 2022

Have you measured the memory impact, by any chance?
I wouldn't have anything against this to be backported - on the contrary. I wrote a little agent for testing reasons that instrumented/transformed Introspector.findCustomizerClass to simply return null and that showed ~5-20% (on average I'd say little less than 10%) improvement for the test suites I have at hand. For normal startups and deployments it's barely noticeable unfortunately. But it's great to hear that you see positive results.

@jhoeller
Copy link
Contributor Author

jhoeller commented Oct 14, 2022

We're substituting the same thing for native images: Introspector.findCustomizerClass to return null. We might keep doing this even with our new introspection algorithm in place, for third-party use of Introspector to be covered.

No memory numbers yet. The footprint is as minimal as possible now, so I would expect a measurable difference. Like with startup time, not sure whether it will really matter in regular application bootstrap, but it's the best we can do in terms of streamlining for the introspection functionality that 99.9% of Spring-based applications actually need.

For the time being, I've extracted a SimpleBeanInfoFactory as an internal delegate for SimpleBeanInfo adaptation in 6.0. This is also prepared for a straightforward backport to 5.3.x whenever we decide to proceed with it: picking a slightly modified version of SimpleBeanInfoFactory (turning public) along with a slightly modified version of PropertyDescriptorUtils.determineBasicProperties (using Introspector.decapitalize instead of StringUtils.uncapitalizeAsProperty).

@dreis2211
Copy link
Contributor

For completeness reasons if someone is interested: https://github.com/dreis2211/remove-introspector-customizer-agent
I've put my little agent in a project for the interested bunch and poor souls that might not be able to try the goodness that @jhoeller is crafting 😉

@jhoeller
Copy link
Contributor Author

The 5.3.x backport should be available in the current snapshot there now: #29330

jhoeller added a commit that referenced this issue Oct 18, 2022
…rn type)

Also avoids unnecessary checks in name-based PropertyDescriptor constructor.

See gh-29320
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

No branches or pull requests

2 participants