Skip to content

AbstractBeanFactory#markBeanAsCreated performance issue due to lock contention [SPR-9780] #14414

Closed
@spring-projects-issues

Description

@spring-projects-issues

Nicko Cadell opened SPR-9780 and commented

We are calling getBean frequently (perhaps too often), but we have noticed that we get some lock contention where the bean name is added to the alreadyCreated set. This is a synchronized set created in the AbstractBeanFactory.

The call stack is typically something like this:

at java.util.Collections$SynchronizedCollection.add(Collections.java:1577)
at org.springframework.beans.factory.support.AbstractBeanFactory.markBeanAsCreated(AbstractBeanFactory.java:1363)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:271)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy$CglibSubclassCreator$LookupOverrideMethodInterceptor.intercept(CglibSubclassingInstantiationStrategy.java:160)

When the markBeanAsCreated method is typically called the beanName already exists in the alreadyCreated set.

A couple of different options come to mind:

The first option would be to change the locking on the alreadyCreated set from a mutex to a reader/writer lock. Change the markBeanAsCreated method to acquire a read lock, then check if the set already contains the bean name, only if it does not contain it, upgrade the read lock to a write lock and add the bean name to the set. This could be slightly more work when a bean is created for the first time but allows for greater concurrency once the beans have been created.

The second option is that the factory is actually a DefaultListableBeanFactory and the configurationFrozen flag is set to TRUE. This means that the isBeanEligibleForMetadataCaching method is overridden to always return TRUE. I believe that the isBeanEligibleForMetadataCaching method in AbstractBeanFactory is the only place that cares about the contents of the alreadyCreated set. So it seems like a waste of time to populate the alreadyCreated set if the configurationFrozen flag is set to TRUE. So the DefaultListableBeanFactory should override the markBeanAsCreated method and do nothing if the configurationFrozen flag is set to TRUE.


Affects: 3.1.1

Issue Links:

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions