-
Notifications
You must be signed in to change notification settings - Fork 38.6k
Description
Affects: 5.3.1 +
Profiling of a complex Spring-based web application shows a bottleneck in AnnotationUtils.getValue()
that cannot be reproduced in JMH benchmarks. Further investigation showed the problem comes from generating deep stack traces in the exception cases (NoSuchMethodException
or Throwable
), and the JMH benchmark uses a very shallow stack (~5) while our application uses a rather deep one (~150). The depth comes largely from nested Tomcat filters, but Spring also contributes.
Exception cases primarily result from lookups of @javax.inject.Qualifier()
and attribute value
, via the following stack trace:
org.springframework.core.annotation.AnnotationUtils.getValue
org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver.checkQualifiers
org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver.isAutowireCandidate
org.springframework.beans.factory.support.DefaultListableBeanFactory.isAutowireCandidate
org.springframework.beans.factory.support.DefaultListableBeanFactory.isAutowireCandidate
org.springframework.beans.factory.support.DefaultListableBeanFactory.isAutowireCandidate
org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject
org.springframework.beans.factory.annotation.InjectionMetadata.inject
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean
I've attached a speed test that reproduces the exception case, and contains an alternative implementation that is faster in all cases (I think). The test can reproduce different stack depths by changing the value of "stackDepth".
Results from my computer:
Running test with extra stack depth of 0
Done with old in 604
Done with old in 598
Done with old in 649
Done with old in 587
Done with old in 557
Done with new in 34
Done with new in 38
Done with new in 32
Done with new in 32
Done with new in 32
Running test with extra stack depth of 50
Done with old in 2038
Done with old in 2020
Done with old in 2083
Done with old in 2003
Done with old in 2027
Done with new in 43
Done with new in 45
Done with new in 47
Done with new in 42
Done with new in 40
Running test with extra stack depth of 150
Done with old in 5126
Done with old in 5154
Done with old in 5211
Done with old in 5148
Done with old in 5150
Done with new in 49
Done with new in 37
Done with new in 33
Done with new in 32
Done with new in 32