Version: Spring 6.2.9
We've observed a performance regression in our application related to Singleton beans that use jakarta.inject.Provider<T> in their constructors, where one of the methods subsequently invokes the provided bean.
Sample:
public class MyService {
private final Provider<AnotherService> anotherServiceProvider;
public MyService(Provider<AnotherService> anotherServiceProvider, ....) {
this.anotherServiceProvider = anotherServiceProvider;
}
public void doSomething() {
AnotherService anotherService = anotherServiceProvider.get();
anotherService.performAction();
}
}
Method Profiling shows:
No such regression is seen in the application when running with Spring 6.1
The issue seen could be due to Step 3 optimization introduced as part of this change. Didnt find this in Spring 6.1 version
The code calls the hasPrimaryConflict that then calls the isTypeMatch that ends up calling getSingleton(...).
We have over 50K beans in the ApplicationContext.
I suspect that the call to getSingleton() within the hasPrimaryConflict method—executed while iterating over all primaryBeanNames—is contending for the global lock, which may be held by other threads creating Spring beans, thereby slowing down bean resolution via Provider<T>.
I believe reversing the if condition logic here could help short-circuit the isTypeMatch check (might not help with this case though).
if (!candidate.equals(beanName) && isTypeMatch(candidate, dependencyType)) {
return true;
}
On a related note, I was under the impression that singleton beans accessed via Provider<T> wouldn't need to go through the resolution process again when calling providerBean.get() more than once. Is there a cache mechanism that can be leveraged to minimize the steps involved in dependency resolution on subsequent get() calls?"
Version: Spring
6.2.9We've observed a performance regression in our application related to Singleton beans that use
jakarta.inject.Provider<T>in their constructors, where one of the methods subsequently invokes the provided bean.Sample:
Method Profiling shows:
No such regression is seen in the application when running with Spring
6.1The issue seen could be due to Step 3 optimization introduced as part of this change. Didnt find this in Spring 6.1 version
The code calls the hasPrimaryConflict that then calls the
isTypeMatchthat ends up callinggetSingleton(...).We have over 50K beans in the
ApplicationContext.I suspect that the call to
getSingleton()within thehasPrimaryConflictmethod—executed while iterating over all primaryBeanNames—is contending for the global lock, which may be held by other threads creating Spring beans, thereby slowing down bean resolution viaProvider<T>.I believe reversing the if condition logic here could help short-circuit the
isTypeMatchcheck (might not help with this case though).On a related note, I was under the impression that singleton beans accessed via
Provider<T>wouldn't need to go through the resolution process again when callingproviderBean.get()more than once. Is there a cache mechanism that can be leveraged to minimize the steps involved in dependency resolution on subsequentget()calls?"