Issue Details (XML | Word | Printable)

Key: SPR-4505
Type: Bug Bug
Status: Resolved Resolved
Resolution: Fixed
Priority: Major Major
Assignee: Juergen Hoeller
Reporter: Leo Kim
Votes: 0
Watchers: 1
Operations

If you were logged in you would be able to see more operations.
Spring Framework

AbstractBeanFactory.getMergedBeanDefinition has performance issues with lock contention when not going through getBean

Created: 26/Feb/08 10:26 PM   Updated: 28/Feb/08 03:36 PM   Resolved: 27/Feb/08 10:14 AM
Component/s: SpringCORE
Affects Version/s: 2.5.1
Fix Version/s: 2.5.2

Time Tracking:
Not Specified

Environment: Linux, Wicket 1.3rc1, Azul

Virtual Machine: Sun JVM - 1.5
Platform: Tomcat - 6.0


 Description  « Hide

While load-testing our webapp, I found that threads servicing requests would block on the mergedBeanDefinitions map in getMergedBeanDefinitions, line 990 in the following:

http://springframework.cvs.sourceforge.net/springframework/spring/src/org/springframework/beans/factory/support/AbstractBeanFactory.java?revision=1.199&view=markup

What was happening was none of my Spring beans were being cached in mergedBeanDefinitions, so each time getMergedBeanDefinition(String) would call getMergedLocalBeanDefinition(String) it would need to reach back down into getMergedBeanDefinition(String, BeanDefinition, BeanDefinition) and grab the mergedBeanDefinitions lock.

Upon further inspection, on lines 1041-1043, I see this:

// Only cache the merged bean definition if we're already about to create an
// instance of the bean, or at least have already created an instance before.
if (containingBd == null && isCacheBeanMetadata() && this.alreadyCreated.contains(beanName)) {
this.mergedBeanDefinitions.put(beanName, mbd);
}

Note how the logic in the predicate belies what the comment is saying. If I read the comment correctly, it's really saying this:

if (isCacheBeanMetadata() && (containingBd == null || this.alreadyCreated.contains(beanName))) {
this.mergedBeanDefinitions.put(beanName, mbd);
}

When I change the code to do this, I no longer experience lock contention because my beans are now cached in mergedBeanDefinitions, and my pages show up quite quickly (from 10 seconds to ~1-2).

I'm not terribly familiar with the internals of Spring so I'm not sure if this is correct. Plus I'm using @SpringBean in Wicket which may be part of the problem, but even so this seems like a serious issue with the code path here, particularly with the predicate logic above and the level of lock contention I was observing – with 40 threads issuing requests against my webapp I was seeing latencies of up to 500 ms on this single lock.



Juergen Hoeller made changes - 27/Feb/08 05:15 AM
Field Original Value New Value
Assignee Juergen Hoeller [ juergen.hoeller ]
Fix Version/s 2.5.2 [ 10681 ]
Juergen Hoeller made changes - 27/Feb/08 07:19 AM
Summary AbstractBeanFactory.getMergedBeanDefinition has performance issues with lock contention AbstractBeanFactory.getMergedBeanDefinition has performance issues with lock contention when not going through getBean
Juergen Hoeller made changes - 27/Feb/08 10:14 AM
Status Open [ 1 ] Resolved [ 5 ]
Resolution Fixed [ 1 ]