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) |
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: - Autowired.xlsx (15.33 kB) - Graph.png (63.26 kB)
Issue Links: - #18188 Improve performance of #getBeanNamesForType() while the BeanFactory configuration is not yet frozen - #16483 Optimize performance of autowiring for Groovy/Grails - #22060 Efficient type matching support for large number of beans
8 votes, 12 watchers
Comment From: spring-projects-issues
Toshiaki Maki commented
The result of measuring start-up time for each pattern
Comment From: contivero
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:
- Using
@Resource(name = "...")
, but this cannot be used with constructor injection. - 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?
Comment From: jhoeller
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.
Comment From: contivero
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.
Comment From: jhoeller
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.