Adding a module to an existing injector

2,903 views
Skip to first unread message

glenviewjeff

unread,
Jun 20, 2012, 8:34:52 AM6/20/12
to google...@googlegroups.com
I'm developing using Guice on Android via Roboguice, and reflection and other operations that Guice uses for binding are horrifically slow.  Before I started optimizing my Guice modules, it was taking about 15 seconds for the app to start.

I'm wondering if I could start with a simple injector that configures just the modules necessary to start up the main screen of the application, and then perform the remaining configuration on a background thread.  To do this, I wouldn't want to repeat the work done in the first createInjector, and ideally would do something like injector.addModules(...), which of course does not exist. 

Is there a way to do this?

Christian Edward Gruber

unread,
Jun 20, 2012, 9:05:11 AM6/20/12
to google...@googlegroups.com
At this point there is no such beast.  createInjector() is a builder, and creates an intact Injector.  

Having said that, you could do something like this with child injectors, but I worry that you would be swapping in a child injector for its parent in a running system, and there are a hell of a lot of concurrency issues at play with that.

But the way you describe… incrementally adding more modules to an existing injector - that sort of goes against the design of Guice, which is that the injector is built with all the information it needs to satisfy bindings.  

We need to do more work on profiling and I think Jesse has some ideas on removing reflection from the mix, but I haven't really gotten a chance to talk a lot of that through.  But start-up times are a definite thing I'm going to be looking at in the next while.  
multiinder
A few questions on that… are you doing initialization work in your constructors/providers?  Can you separate out expensive operations into service startup methods, and maybe use a MulltiBinder to register services, and have them started up separately?  A lot of startup times can be mitigated by doing less work in the wiring itself, which is already not recommended.  I don't know your design, so I can only comment abstractly. 

Christian

--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To view this discussion on the web visit https://groups.google.com/d/msg/google-guice/-/bFax3gkE66oJ.
To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.

glenviewjeff

unread,
Jun 20, 2012, 9:11:04 AM6/20/12
to google...@googlegroups.com
Christian, 95% of the startup code is Guice binding code; and there's zero I/O, database/network operations, etc.  If you're an Android developer, (or even if you're not but are willing to install the Android tools so you can use Traceview), I can send you the tracing file if you'd like to see for yourself. 
To unsubscribe from this group, send email to google-guice+unsubscribe@googlegroups.com.

Christian Edward Gruber

unread,
Jun 20, 2012, 9:28:02 AM6/20/12
to google...@googlegroups.com

On Jun 20, 2012, at 9:11 AM, glenviewjeff wrote:

> Christian, 95% of the startup code is Guice binding code; and there's zero I/O, database/network operations, etc. If you're an Android developer, (or even if you're not but are willing to install the Android tools so you can use Traceview), I can send you the tracing file if you'd like to see for yourself.
>

Not an android guy (and am in the middle of six things - won't be able to start up a new environment for this - but I trust you). Reflection can be expensive in constrained environments. I am hoping to do some benchmarking with caliper this coming quarter, and look at key areas to speed up. As a personal musing, I wonder where most of that work is… the reflection of finding @Inject constructors and using them, or of looking up provider methods. etc. Which bits would be the biggest hits. And byte code manipulation might not be faster for your case, but a code-gen approach might.

While I can't setup the env right now, when I start benchmarking, it'd be good to look at this. Please feel free to send me the trace-view, and I'll dig through it when I can get some time for this.

C.

glenviewjeff

unread,
Jun 20, 2012, 9:32:54 AM6/20/12
to google...@googlegroups.com
One other thing.. As far as startup times go, I it should be possible for Guice to support a binding cache.  I just don't know how difficult this would be for someone to implement.  If this were implemented even a 10-15 second binding would be much more tolerable if it were just a one-time startup/"installation" operation.

glenviewjeff

unread,
Jun 20, 2012, 9:42:35 AM6/20/12
to google...@googlegroups.com
I haven't been keeping detailed records, but from what I have been seeing, I think much of my performance hits and optimization improvements has come from uglifying my code by removing annotations from injected parameters, replacing @Assisted/FMB with boilerplate factories, and creating boilerplate generic implementations instead of using TypeLiteral.

Christian Edward Gruber

unread,
Jun 20, 2012, 10:13:56 AM6/20/12
to google...@googlegroups.com

On Jun 20, 2012, at 9:42 AM, glenviewjeff wrote:

> I haven't been keeping detailed records, but from what I have been seeing, I think much of my performance hits and optimization improvements has come from

Awesome initial list. Thanks.

> uglifying my code by removing annotations from injected parameters,

Which - @Named("foo") and @MyBindingAnnotation, or are you talking about something else.

Not sure it's that ugly to implement tagging interfaces instead of binding annotations (depends on how verbose and how many of these you have to make. Matter of style I suppose, but I can see it being worth it if you're feeling the pain here.

> replacing @Assisted/FMB with boilerplate factories

I can understand. I really think that this could benefit from some codegen/bytecodegen love.

> and creating boilerplate generic implementations instead of using TypeLiteral.

Yeah… grr. Type erasure sucks. Workarounds suck also. :(


Christian.

limpb...@gmail.com

unread,
Jun 20, 2012, 10:20:24 AM6/20/12
to google...@googlegroups.com
I'm going to be investigating this. I'm working on an Android project that uses Guice extensively and we're suffering some performance problems. I'll keep this list posted with my progress. I expect to have something within a few weeks.

Christian Edward Gruber

unread,
Jun 20, 2012, 10:33:38 AM6/20/12
to google...@googlegroups.com
On Jun 20, 2012, at 10:20 AM, je...@swank.ca wrote:
> I'm going to be investigating this. I'm working on an Android project that uses Guice extensively and we're suffering some performance problems. I'll keep this list posted with my progress. I expect to have something within a few weeks.

Thanks Jesse. -cg.


Sam Berlin

unread,
Jun 20, 2012, 10:45:14 AM6/20/12
to google...@googlegroups.com
Fantastic.  It'll be awesome to get Guice optimized again (and optimized for the first time on Android).  We lost a bit of speed in the 2.0 release, and the 3.0 release probably didn't help anything either.
 sam

On Wed, Jun 20, 2012 at 10:20 AM, je...@swank.ca <limpb...@gmail.com> wrote:
I'm going to be investigating this. I'm working on an Android project that uses Guice extensively and we're suffering some performance problems. I'll keep this list posted with my progress. I expect to have something within a few weeks.

--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To view this discussion on the web visit https://groups.google.com/d/msg/google-guice/-/XnRGqjMj0XQJ.

To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.

Stuart McCulloch

unread,
Jun 20, 2012, 10:53:29 AM6/20/12
to google...@googlegroups.com
On 20 Jun 2012, at 15:20, je...@swank.ca wrote:

> I'm going to be investigating this. I'm working on an Android project that uses Guice extensively and we're suffering some performance problems. I'll keep this list posted with my progress. I expect to have something within a few weeks.

Cool, let me know if I can help out :)

glenviewjeff

unread,
Jun 20, 2012, 11:37:13 AM6/20/12
to google...@googlegroups.com
See response below:

 
On Wednesday, June 20, 2012 9:13:56 AM UTC-5, Christian Gruber wrote:
> uglifying my code by removing annotations from injected parameters,

Which - @Named("foo") and @MyBindingAnnotation, or are you talking about something else.  
Not sure it's that ugly to implement tagging interfaces instead of binding annotations (depends on how verbose and how many of these you have to make.  Matter of style I suppose, but I can see it being worth it if you're feeling the pain here.
 
I mean annotations like:

 @Inject private ClassA(@Annotation1 InterfaceB b, @Named("name") InterfaceC c) {}

What you mean by "tagging interfaces"?  If there's a better workaround, I'd like to know.  From what I remember, I've been avoiding these through a number of different ways, either hard coding the implementation classes (like asking for a UniqueClassB instead of InterfaceB) or using PrivateModules. 

glenviewjeff

unread,
Jun 20, 2012, 11:40:50 AM6/20/12
to google...@googlegroups.com
Jesse, if you haven't already been talking to Bob Lee, I hear he's been doing some optimizations of his own with the Square app.  I'm not sure if they are application or Guice core optimizations.  It wouldn't hurt to get in touch with him.  I tried contacting him a couple of times over the past couple months, but he doesn't know me from Adam, and haven't heard back.

limpb...@gmail.com

unread,
Jun 21, 2012, 3:12:50 AM6/21/12
to google...@googlegroups.com
On Wednesday, June 20, 2012 8:40:50 AM UTC-7, glenviewjeff wrote:
Jesse, if you haven't already been talking to Bob Lee, I hear he's been doing some optimizations of his own with the Square app.  I'm not sure if they are application or Guice core optimizations.

I'll talk to Bob; he's my boss!


It wouldn't hurt to get in touch with him.  I tried contacting him a couple of times over the past couple months, but he doesn't know me from Adam, and haven't heard back.

I get a lot of email and simply don't have time to address all the messages coming in. The best way to discuss software projects with me is on those projects' mailing lists: that way everyone gets to participate in the conversation. I suspect Bob is in a similar situation!

glenviewjeff

unread,
Jun 21, 2012, 2:25:46 PM6/21/12
to google...@googlegroups.com
FYI for those of you that hadn't already read the Roboguice group thread, in order to support static injection, module bindings are executed twice and double the startup binding times.  Since I don't use static injection and can't imagine why anybody would, I commented out the below loop RoboGuice.setBaseApplicationInjector, rebuilt RoboGuice, and cut my startup time almost in half.

        // Do a little rewriting on the modules first to
        // add static resource injection
/*        for(Element element : Elements.getElements(modules)) {
            element.acceptVisitor(new DefaultElementVisitor<Void>() {
                @Override
                public Void visit(StaticInjectionRequest element) {
                    getResourceListener(application).requestStaticInjection(element.getType());
                    return null;
                }
            });
        } */

glenviewjeff

unread,
Jul 9, 2012, 10:29:04 PM7/9/12
to google...@googlegroups.com
Any updates from any of you guys?  Jesse, did you hear back from Bob? 

As an update for how I'm speeding up my bindings on Android, it seems like the worst source of most of the slow binding is binding generics via typeliteral. I just made a tremendous gain by being a human compiler and explicitly deriving about fifty or so concrete classes from my generic ones.  I still have a lot of tedious work left to get my app to start up in a reasonable time (1-2 seconds).  I've had to spend several very unpleasant weeks doing this.

I wish there were some way to generate the code for this or save the bindings via serialization so binding became a single compile-time or installation-time operation.

Thanks,
Jeff

Sam Berlin

unread,
Jul 9, 2012, 10:49:33 PM7/9/12
to google...@googlegroups.com
It theoretically should be possible to do code generation, providing you use a subset of the binding DSL.  This is what Gin does (no reflection at all), and it works well.
 sam

--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To view this discussion on the web visit https://groups.google.com/d/msg/google-guice/-/zPJKG2wAEGUJ.

To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.

glenviewjeff

unread,
Jul 20, 2012, 10:59:13 AM7/20/12
to google...@googlegroups.com
On Wednesday, June 20, 2012 7:34:52 AM UTC-5, glenviewjeff wrote:
I'm wondering if I could start with a simple injector that configures just the modules necessary to start up the main screen of the application, and then perform the remaining configuration on a background thread.  To do this, I wouldn't want to repeat the work done in the first createInjector, and ideally would do something like injector.addModules(...), which of course does not exist. 

Is there a way to do this?


Injector.createChildInjector() was exactly what I was looking for.  I had been implementing this manually.   Apparently, I had been relying too heavily on the Guice website documentation without reading through the Javadocs.  :( 


glenviewjeff

unread,
Aug 16, 2012, 12:41:29 PM8/16/12
to google...@googlegroups.com
Jesse, have you made any progress on this or talked to Bob about his Guice on Android optimization ideas?


On Wednesday, June 20, 2012 9:20:24 AM UTC-5, je...@swank.ca wrote:

glenviewjeff

unread,
Sep 29, 2012, 11:26:05 PM9/29/12
to google...@googlegroups.com
Well apparently Jesse has made some progress on this:

If others haven't heard, there's a new Guice-compatible DI tool called Dagger released by Square.  It does code generation so there's no slow startup.

I'm certainly glad I didn't take a stab at re-using Gin's code generation to do this.  I look forward to the possibility of eliminating my six-second spinners during app startup, and deleting all my boilerplate interfaces I had to kludge to speed up Guice startup.

Jeff
Reply all
Reply to author
Forward
0 new messages