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

Performance regression on startup (in particular in AnnotationUtils) [SPR-13621] #18199

Closed
spring-issuemaster opened this issue Oct 29, 2015 · 3 comments

Comments

Projects
None yet
2 participants
@spring-issuemaster
Copy link
Collaborator

commented Oct 29, 2015

Stéphane Nicoll opened SPR-13621 and commented

There is a major performance regression on annotations lookup in Spring Framework 4.2. We found out that a basic Spring Boot application was 10% slower between 1.2 and 1.3. We did some investigation and found out that a Spring boot 1.3 app based on 4.2 was also 10% slower than the same app on 4.1

One of the major hotspot difference is AnnotationUtils.findAnnotation. On 4.1 its own time is 23 ms (232ms in total) while on 4.2 it is 1,936ms (5,340ms in total)


Affects: 4.2.2

Issue Links:

  • #21208 Reduce ClassUtils.forName overhead (in particular for annotation introspection purposes)
  • #21271 Avoid repeated superclass introspection in AnnotationUtils.findAnnotation

1 votes, 10 watchers

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 2, 2015

Juergen Hoeller commented

Based on my attempts today, a particularly wasteful part seems to be the synthesize step for annotations on re-retrieval: While we have been caching the original annotation result, we always re-synthesize the entire annotation for every lookup call... I've modified this to cache the synthesized result now which should provide a significant boost for re-retrieval attempts. However, I have no idea how much of a difference this makes in actual Boot startup time, so please re-run the tests there, Stéphane Nicoll...

If this doesn't provide enough benefit yet, we could also try to skip the synthesize step altogether for lookup attempts where it doesn't make an actual difference, i.e. where the calling code is ok with aliased attributes to be exposed independently (which it may signal through a boolean flag). However, let's see where the change above takes us first.

Juergen

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 5, 2015

Juergen Hoeller commented

A few further steps taken in the meantime:

We're avoiding our rather expensive annotation retrieval algorithm in common callers of AnnotatedElementUtils when there are no annotations to begin with: e.g. in StandardAnnotationMetadata, AutowiredAnnotationBeanPostProcessor, AnnotationTransactionAttributeSource. StandardAnnotationMetadata also caches the annotation array now, avoiding repeated re-retrieval.

AnnotatedElementUtils consistently operates on the actual annotation type if available, avoiding String name comparisons in favor of annotation type identity checks wherever possible. Also, it avoids double getDeclaredAnnotations/getAnnotations checks on anything other than Classes now - since they'll always deliver the same result for Methods etc anyway, just in a wasteful fresh array.

I've also fixed our new 4.2 order determination check in ConfigurationClassUtils so that it only kicks in for actual configuration candidates; it was running through an unnecessary Order annotation lookup for every single bean in the context before.

Juergen

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 5, 2015

Juergen Hoeller commented

As a further step, we're avoiding annotation synthesizing for getAnnotationAttributes retrieval now, in particular affecting ASM-based introspection during component scans.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.