Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AnnotationUtils performance degrades with deep stacks #32921

Closed
jengebr opened this issue May 29, 2024 · 2 comments
Closed

AnnotationUtils performance degrades with deep stacks #32921

jengebr opened this issue May 29, 2024 · 2 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: backported An issue that has been backported to maintenance branches type: enhancement A general enhancement
Milestone

Comments

@jengebr
Copy link

jengebr commented May 29, 2024

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

AnnotationUtilsSpeedTest.java.txt

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label May 29, 2024
@jhoeller jhoeller added in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels May 29, 2024
@jhoeller jhoeller self-assigned this May 29, 2024
@jhoeller jhoeller added this to the 6.1.9 milestone May 29, 2024
@jhoeller jhoeller added the for: backport-to-6.0.x Marks an issue as a candidate for backport to 6.0.x label May 29, 2024
@github-actions github-actions bot added status: backported An issue that has been backported to maintenance branches and removed for: backport-to-6.0.x Marks an issue as a candidate for backport to 6.0.x labels May 29, 2024
@jhoeller jhoeller added the for: backport-to-5.3.x Marks an issue as a candidate for backport to 5.3.x label May 29, 2024
@github-actions github-actions bot removed the for: backport-to-5.3.x Marks an issue as a candidate for backport to 5.3.x label May 29, 2024
jhoeller added a commit that referenced this issue Jun 3, 2024
jhoeller added a commit that referenced this issue Jun 3, 2024
@jhoeller
Copy link
Contributor

jhoeller commented Jun 4, 2024

This is available in current 6.1.9 / 6.0.22 / 5.3.37 snapshots already. Feel free to give it an early try!

@jengebr
Copy link
Author

jengebr commented Jun 5, 2024

Dev testing confirms the change eliminated the NoSuchMethodExceptions. Thanks! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: backported An issue that has been backported to maintenance branches type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

3 participants