Perform basic property determination without java.beans.Introspector
Closed this issue · 5 comments
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.
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.
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.
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
).
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 😉