Details

Description

The Autowiring algorithms tries to work out the dependencies by building up the Beans. If this fails, a BeanCreationException is thrown, caught and then a different way to handle the dependencies is tried. In some situations this results in slow performance and it is probably also not the nicest programming style.

Activity

This problem is really bad if you use a lot of web-scoped beans and @Autowired with web-scoped beans currently uses about 75% of our total CPU time on our web server. Since the factory is not caching anything by type, it ends up iterating the entire factory a lot. And web-scoped beans are created per-request.

Kristian Rosenvold
added a comment - 02/Jun/10 6:48 PM This problem is really bad if you use a lot of web-scoped beans and @Autowired with web-scoped beans currently uses about 75% of our total CPU time on our web server. Since the factory is not caching anything by type, it ends up iterating the entire factory a lot. And web-scoped beans are created per-request.

Any chance to see some work on this? The performance of looking up Spring beans by type is a bother for us as well.

We solved this outside of Spring by using this workaround:

getBean(Class<T> type) {

String name = type.getName() + "#0";

return getBean( name, type );

}

The idea is that for most singletons, there is only a single implementation, so the ID can be omitted and Spring will use the type of the bean to generate a name. This means that you need to do some extra work for interfaces or that you must always request beans using interface by a specific ID and never by type.

But it's a poor solution. It's pretty simple to cache the bean definition lookup in getBean(Class<T> type) and that would give a huge performance boost without the need for any hacks.

Aaron Digulla
added a comment - 23/Feb/12 6:52 AM Any chance to see some work on this? The performance of looking up Spring beans by type is a bother for us as well.
We solved this outside of Spring by using this workaround:
getBean(Class<T> type) {
String name = type.getName() + "#0";
return getBean( name, type );
}
The idea is that for most singletons, there is only a single implementation, so the ID can be omitted and Spring will use the type of the bean to generate a name. This means that you need to do some extra work for interfaces or that you must always request beans using interface by a specific ID and never by type.
But it's a poor solution. It's pretty simple to cache the bean definition lookup in getBean(Class<T> type) and that would give a huge performance boost without the need for any hacks.

Mike Youngstrom
added a comment - 24/Feb/12 8:55 AM I've been told this is a risky fix because it is right in the core of some complex code. NOW is the perfect time attempt to fix this since you are so early in the 3.2 release cycle!

Thanks, Kristian for the patch. With minor modifications, it has been applied and indeed solves the problem nicely.

At the time of this writing the snapshot containing these changes has just finished publishing. There are a large number of watchers on this issue – please consider taking the latest 3.2.0.BUILD-SNAPSHOT for a spin and provide any feedback. Note that we'll be shipping this change with 3.2 M1 within a day or two as well; but naturally any feedback prior to that would be great.

Chris Beams
added a comment - 27/May/12 9:04 AM Thanks, Kristian for the patch. With minor modifications, it has been applied and indeed solves the problem nicely.
At the time of this writing the snapshot containing these changes has just finished publishing. There are a large number of watchers on this issue – please consider taking the latest 3.2.0.BUILD-SNAPSHOT for a spin and provide any feedback. Note that we'll be shipping this change with 3.2 M1 within a day or two as well; but naturally any feedback prior to that would be great.
commit 4c7a1c0a5403b35dd812dae1f2a753538928bb32 (HEAD, SPR-6870)
Author: Chris Beams <[email protected]>
Date: Sun May 27 17:40:33 2012 +0300
Cache by-type lookups in DefaultListableBeanFactory
Prior to this change, by-type lookups using DLBF#getBeanNamesForType
required traversal of all bean definitions within the bean factory
in order to inspect their bean class for assignability to the target
type. These operations are comparatively expensive and when there are a
large number of beans registered within the container coupled with a
large number of by-type lookups at runtime, the performance impact can
be severe. The test introduced here demonstrates such a scenario clearly.
This performance problem is likely to manifest in large Spring-based
applications using non-singleton beans, particularly request-scoped
beans that may be created and wired many thousands of times per second.
This commit introduces a simple ConcurrentHashMap-based caching strategy
for by-type lookups; container-wide assignability checks happen only
once on the first by-type lookup and are afterwards cached by type
with the values in the map being an array of all bean names assignable
to that type. This means that at runtime when creating and autowiring
non-singleton beans, the cost of by-type lookups is reduced to that of
ConcurrentHashMap#get.
Issue: SPR-6870