dagger
dagger copied to clipboard
All providers from all modules are class loaded during ObjectGraph.create
All auto-generated providers (Provide<SomeClass>ProvidesAdapter) are class loaded by Dalvik during ObjectGraph.create as a result of the implementation of ModuleAdapter#getBindings:
map.put("com.example.ThingYouNeed", new ProvideThingYouNeedProvidesAdapter(module));
This line of code requires that Dalvik both class load and then invoke <clinit> and <init> for ProvideThingYouNeedProvidesAdapter. Because Dagger invokes the getBindings method for all modules in the graph, this effectively means that there is an up front class load and init penalty for every class in the purview of Dagger.
I believe this can be fixed by simply changing ModuleAdapter to use:
map.put("com.example.ThingYouNeed", "com.example.ProvideThingYouNeedProvidersAdapter");
And then using Class.forName explicitly to get a new instance of the adapter class only when the object instance is requested. However it's unclear whether the Class.forName overhead would not be a net performance loss due to decreased performance versus implicit class loading.
I modified Dagger's android-simple example to demonstrate this problem. See: https://github.com/jasta/dagger/commits/master for source, and in particular see dvm-debug.log which shows the instrumented result of Dalvik with LOG_CLASS_LOADING 1 enabled to visualize the provider classes being loaded during ObjectGraph.create.
Interesting! Care to submit a benchmark? Caliper is handy.
Perhaps, although I did not select Dagger as my implementation after all so I must admit that my motivation for optimizing it has gone way down since I did this investigation months ago :)
If we want to investigate this further we probably should:
- [ ] backfill test of
ModuleAdapterProcessor.generateModuleAdapter(). This will easily help show any codegen differences if we take any action here. We can do this similarly toInjectAdapterGenerationTest. - [ ] add a caliper test module, which first benchmark could be written to show the time to
ObjectGraph.createwith 1000 bindings? (what's the best count here?) - [ ] figure out a bench for Dalvik, presuming there's not a direct correlation there..
This should be done after @cgruber recent pull requests are merged, but they can be done independently by folks. Once these are in, we have a solid place to test ideas including the class.forname thing that might be promising. I'd be hesitant to do too much before, though. my 2p anyway.
Looking at this realistically, I can't promise I can run through all of this, but I will start on backfilling the generation test tomorrow.