Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.Sign up
XmlBeanDefinitionReader runs 10x slower due to resetBeanDefinition check [SPR-8318] #12966
When trying to load 700+ beans using:
it takes over 5 min using the 2.5.3 (or 3.0.5) library, but only 24 sec using the 2.0.4 library. This seems to only occur on the AIX JVM.
Please see the attached zip with example scripts loadbeans256.sh and loadbeans204.sh
We have also tested with spring 3.0.5 and the results are similar to 2.5.6.
Thanks for your help with this. This is the first time I've filed a defect so please let me know if I'm missing anything.
Affects: 2.5.6, 3.0.5
Backported to: 3.2.11
1 votes, 6 watchers
Matt McQuarrie commented
After further testing this issue seems to occur on all JVMs. HotSpot, JRockit, and IBM's JVM seem to have this issue with varying severities. For example, HotSpot takes 10x longer to load the example project's beans while IBM's JVM takes 20x longer.
Jonathan Keller commented
Adding some more information on this one:
I also just did a little research into the startup time problem of KFS and the difference between Spring 2.0.4 and 2.5.6. The problem comes partially in that we have almost 100,000 beans defined between all our XML files, not counting those which are in the Rice jars. But more than that is some code that Spring added by 2.5.6 which is intended to improve the handling of parent beans. (They seemed to be working before, so I don't know what changed that made this necessary.)
The problem is a new line at the end of the registerBeanDefinition() method:
This method is designed to find any beans for which the current bean is a parent and "reset" the definition in order to ensure that the proper values are being inherited. This unfortunately requires iterating over all beans previously defined. In the selection of the parsing I traced below, which processed about 6,000 bean definitions, there were almost 17,000,000 retrievals of beans simply to check if the current bean was its parent. This method is recursive, so if there is a parent, then it does the iteration all over again.
So, it seems that the more beans which use the inheritance which makes Spring so useful, the more we impact performance. It seems to be that a fix for this would be for Spring to index the beans by their parents (another HashMap?) so such extensive iteration would not be necessary. It seems it would be fairly easy to update this method (and a couple others) to maintain/check this new cache to greatly reduce the application startup time.
Jonathan Keller commented
I'm attaching a diff file containing the changes I made locally to the DefaultListableBeanFactory class to implement a possible solution. This did immediately decrease the time needed to process all our beans.
It seems to work for the use case which we have for Spring. I don't know if there are other edge cases that may exist for which it could break, but it may be a start.
diff DefaultListableBeanFactory-original-spring-2.5.6.txt DefaultListableBeanFactory.java -b -u
John Walker commented
VM Ware has requested to become a Commercial Affliate for Kuali Open Source. It would be helpful to the Kuali Community if someone at VMWare/Spring could address the slowness problem experienced/witnessed between versions 2.0.4 and 2.5.6. Thanks.
Kristina Taylor commented
Kuali Rice has recently done a Spring 4.0.5 upgrade but is still experiencing this problem. We verified that the patch submitted by Jonathan Keller, when merged with the Spring 4.0.5 version, brings our times back to normal from the 10x slowdown we were experiencing. Please reconsider applying this patch as it is a pretty major issue with performance.
Juergen Hoeller commented
I've optimized registerBeanDefinition to only call resetBeanDefinition in case of a pre-existing bean definition or a pre-existing singleton instance. This means that resetBeanDefinition won't be called at all for regular early bean definition registration phases (such as with XML file parsing).
Introducing a parent-children association cache would be an option as well but requires clean management of both ends of that association, i.e. if a parent gets removed or one of the children gets removed... That didn't seem to be worth it, if the 90% case can be addressed as above.