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

Autowiring with @Autowired/@Inject get much slower than with @Resource as the number of classes increases [SPR-13086] #17677

Closed
spring-projects-issues opened this issue May 29, 2015 · 5 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented May 29, 2015

Toshiaki Maki opened SPR-13086 and commented

I had a performance issue at the project which had a few thousand of @Component classes. The start up time of the application took a few minutes.
That application used @Autowired for autowiring and the start up time reduced to less than one minute after swiching @Autowired to @Resource.

So, I measured the time to create ApplicationContext for the following patterns:

  • Pattern1 @Inject
  • Pattern2 @Inject + @Named
  • Pattern3 @Autowired
  • Pattern4 @Autowired + @Qualifier
  • Pattern5 @Resource

I generated a lot of components with the script .
This script generates N Controller s, Service s, and ServiceImpl s.
The result was as follows:

N 1000 2000 3000 4000 5000 6000
Pattern 1 8549 21171 35018 55879 86589 112140
Pattern 2 9547 19830 35662 57174 85846 108736
Pattern 3 9282 19121 35586 57377 81274 106385
Pattern 4 9126 19394 36292 57704 81762 110087
Pattern 5 6663 11203 16427 23868 30603 33978
(unit=milli second)

Graph.png

At that time, I used Spring 4.1.6.RELEASE with the following environment:

  • OS: Windows 7 64bit
  • CPU: Core i7-4610M CPU @ 3.00GHz
  • RAM: 16GB
  • JDK: Oracle JDK 8u45

Previous versions will be same.

@Inject and @Autowired (Pattern 1-4) seems to take O(N^2) time.
On the other hand @Resource seems to take O(N) time.

I guess autowirng "by name" is faster than "by type" because the number of candidates for each "type" increase as the target of component-scan increases and @Qualifier, @Named doesn't give any optimization for autowiring.

So I hope

  • Autowiring by type gets faster
  • @Autowired + @Qualifier and @Inject + @Named became as fast as @Resource

Affects: 4.1.6

Attachments:

Issue Links:

8 votes, 12 watchers

@spring-projects-issues
Copy link
Collaborator Author

Toshiaki Maki commented

The result of measuring start-up time for each pattern

@contivero
Copy link

Has there been any progress with this? I've run into issues with slow application start up and tests due to this, and I haven't found a way of wiring specifically by name other than:

  1. Using @Resource(name = "..."), but this cannot be used with constructor injection.
  2. Having to define the bean in XML and using <constructor-arg name="..." ref="..." />. I couldn't find a way of wiring by name with annotations (from what I understand, @Qualifier is used to disambiguate, so we are still matching by type first). I can also not specify an optional dependency with <constructor-arg> (as with @Autowired(required = false)).

Another possibility could be defining beans with @Bean and @Configuration, but I don't see anything akin to an @Resource at the parameter level of the constructor.

Is there any other solution for wiring by name using constructor injection and annotations that I'm missing?

@jhoeller
Copy link
Contributor

We intend to revisit this within our common dependency injection algorithm, shortcutting constructor parameter resolution when the parameter name matches a bean name as long as the bean type matches as well (and as long as no primary beans overrule such a match). See #28122 for that effort, hopefully addressing this ticket along with it in the 6.2 timeframe.

@jhoeller jhoeller modified the milestones: 6.x Backlog, 6.2.x Dec 18, 2023
@contivero
Copy link

It's nice that this is finally tackled, but I hope there are other solutions considered or that the shortcutting is general enough for our usecase. I'm saying this because our bean names usually match the name of the class / interface, e.g. PersonService instead of personService, and of course the parameter names don't match the name because it's against convention to have a parameter name start with an uppercase letter. Unless the name matching is case insensitive, it wouldn't help our case. It would be nice if @Qualifier could match by name (instead of trying to match first by type), or if there is some other way to specify the resource to inject when using annotations (instead of XML) and constructor injection.

In any case, I want to stress that it's good that you have this among the milestones, and even if the initial solution doesn't work for us, it might open doors for other future improvements with which we might be able to use to tackle our performance issues with beans wiring.

@jhoeller jhoeller modified the milestones: 6.2.x, 6.2.0-M1 Feb 19, 2024
@jhoeller
Copy link
Contributor

In addition to the shortcut for parameter name matches in #28122, there is equivalent shortcut behavior for @Qualifier/@Named matching the target bean name now.

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) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

3 participants