I've always thought that, when working with Dagger2, we should use @Reusable
scope instead of @Singleton
if we don't need the guarantee to get always the same instance, since @Singleton
used double checking, which is expensive and slow...
However, I've made a simple performance tests and here are the results:
Reusable 4474 ms
Singleton 3603 ms
Here is the code:
@Singleton
@Component
interface AppComponent {
fun getReusable(): ReusableFoo
fun getSingleton(): SingletonFoo
}
@Reusable
class ReusableFoo @Inject constructor()
@Singleton
class SingletonFoo @Inject constructor()
class TestClass {
@Test
fun test() {
val component = DaggerAppComponent.builder().build()
measure {
component.getReusable()
}
measure {
component.getSingleton()
}
}
private fun measure(block: () -> Unit) {
val start = System.currentTimeMillis()
(0..1000000000).forEach { block() }
println(System.currentTimeMillis() - start)
}
}
The same phenomenon when constructing heavier class (I've tried with Retrofit
) and with @Provide
annotated methods instead of constructor injection.
Did I make a mistake in my test or simply @Reusable
is slower? If so, where should we use it? Does it have any benefits over @Singleton
?