Reputation: 53
There has been a similar question asked already at (https://groups.google.com/forum/#!searchin/google-guice/Should$20Guice-Injected$20DAO$27s$20be$20Singletons$3F/google-guice/3B8XrwB-p18/B6OF13HWRnEJ) but I don't think it has received a satisfying answer yet.
The baseline: We are using Guice in a JSF/Primefaces webapplication running on Tomcat. Persistence is handled via JPA/Hibernate.
Right now ALL our DAOs (approx. one per Entity) are annotated as @Singleton. The only reason for this seem to be performance concerns as another (non JSF but Webservice) part of the application will receive thousands of hits per seconds and our main developer believes, that constructing a DAO Singleton once and then getting it in a synchronized way is cheaper than to always inject a new instance (which is the Guice Default Scope). This goes contrary to what the Google Guice Wiki writes about Scopes: If the object is stateless and inexpensive to create, scoping is unnecessary. Leave the binding unscoped and Guice will create new instances as they're required...Although singletons save object creation (and later garbage collection), initialization of the singleton requires synchronization; ...
Now, what exactly does "initialization of the singleton" mean in this context? Is initialization done once? Everytime it is injected?
Is the assumption correct that, with the above scenario (thousands of hits per second) using @Singleton annotated DAOs is faster and better resource wise than using Default Scope?
As we use @Singleton for our DAOs we don't inject the EntityManager directly but use an EntityManagerProvider which, as I understand it, is the correct way as the Provider is considered threadsafe which is a requirement for @Singleton. Is there a "Google approved" way to include Hibernate using DAOs in your web application?
Upvotes: 1
Views: 4533
Reputation: 12922
Although singletons save object creation (and later garbage collection), initialization of the singleton requires synchronization; ...
Now, what exactly does "initialization of the singleton" mean in this context? Is initialization done once? Everytime it is injected?
Here is the implementation of the singleton scope (it is slightly different in the released version of Guice, but the following points still stand). Every time a singleton-scoped dependency is injected anywhere, the get()
method on that provider will be called to get the instance.
Double-checked locking is used so that after the singleton has been created for the first time, future calls to get()
are cheap: they read a single volatile
field and return.
On the other hand, using @Singleton
DAOs means you have to access the EntityManager
through a Provider
in every method, which involves looking up the EntityManager
in a HashMap
in a ThreadLocal
somewhere.
Conclusion: the only way to find what choice is better for performance is to benchmark both and pick the faster one. You'll probably find that both choices are fast enough, in which case you should pick the cleanest one.
Upvotes: 4