Skip to content

Instantly share code, notes, and snippets.

@esmasui
Created March 8, 2013 17:50
Show Gist options
  • Select an option

  • Save esmasui/5118364 to your computer and use it in GitHub Desktop.

Select an option

Save esmasui/5118364 to your computer and use it in GitHub Desktop.
package com.uphyca.daggerperformance;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.text.DecimalFormat;
import java.util.concurrent.Callable;
import javax.inject.Inject;
import javax.inject.Qualifier;
import javax.inject.Singleton;
import junit.framework.TestCase;
import com.google.inject.AbstractModule;
import com.google.inject.BindingAnnotation;
import com.google.inject.CreationException;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Provider;
import com.google.inject.Scopes;
import dagger.Module;
import dagger.ObjectGraph;
import dagger.Provides;
/**
* Based on
* http://www.jroller.com/Solomon/entry/spring_2_5_perfomance_improvements
*/
public class DaggerPerformanceTest extends TestCase {
public void testGuice() throws Exception {
// Once warm up. Takes lazy loading out of the equation and ensures we
// created the graphs properly.
validate(daggerFactory, false);
validate(juiceFactory, false);
validate(byHandFactory, false);
System.err.println("===================================");
System.err.println("Prototypes :");
System.err.println("===================================");
System.err.println("======");
System.err.println("Concurrent:");
System.err.println("======");
for (int i2 = 0; i2 < 5; i2++) {
concurrentlyIterate(daggerFactory, "Dagger: ", false);
concurrentlyIterate(juiceFactory, "Guice: ", false);
concurrentlyIterate(byHandFactory, "By Hand: ", false);
System.err.println();
}
System.err.println("======");
System.err.println("Single Threaded:");
System.err.println("======");
for (int i2 = 0; i2 < 5; i2++) {
iterate(daggerFactory, "Dagger: ", false);
iterate(juiceFactory, "Guice: ", false);
iterate(byHandFactory, "By Hand: ", false);
System.err.println();
}
System.err.println("===================================");
System.err.println("SingleTons :");
System.err.println("===================================");
System.err.println("======");
System.err.println("Concurrent:");
System.err.println("======");
for (int i2 = 0; i2 < 5; i2++) {
concurrentlyIterate(daggerSingletonFactory, "Dagger: ", true);
concurrentlyIterate(juiceSingletonFactory, "Guice: ", true);
concurrentlyIterate(byHandSingletonFactory, "By Hand: ", true);
System.err.println();
}
System.err.println("Single:");
for (int i2 = 0; i2 < 5; i2++) {
iterate(daggerSingletonFactory, "Dagger: ", true);
iterate(juiceSingletonFactory, "Guice: ", true);
iterate(byHandSingletonFactory, "By Hand: ", true);
System.err.println();
}
}
public static class ProviderHolder {
@Inject
javax.inject.Provider<Foo> provider;
}
@Module(entryPoints = { Foo.class, ProviderHolder.class })
public static class DaggerFactoryModule {
@Provides
Tee provideTee(TeeImpl tee) {
return tee;
}
@Provides
Bar provideTee(BarImpl bar) {
return bar;
}
@Provides
Foo provideFoo(FooImpl foo) {
return foo;
}
@Provides
@I
int provideInt() {
return 5;
}
@Provides
@S
String provideString() {
return "test";
}
}
static final Callable<Foo> daggerFactory = new Callable<Foo>() {
final javax.inject.Provider<Foo> fooProvider;
{
ObjectGraph injector = ObjectGraph
.create(new DaggerFactoryModule());
ProviderHolder holder = new ProviderHolder();
injector.inject(holder);
fooProvider = holder.provider;
}
public Foo call() throws Exception {
return fooProvider.get();
}
};
@Module(entryPoints = { Foo.class, ProviderHolder.class })
public static class DaggerSingletonFactoryModule {
@Provides
Tee provideTee(TeeImpl tee) {
return tee;
}
@Provides
@Singleton
Bar provideTee(BarImpl bar) {
return bar;
}
@Provides
@Singleton
Foo provideFoo(FooSingletonImpl foo) {
return foo;
}
@Provides
@I
int provideInt() {
return 5;
}
@Provides
@S
String provideString() {
return "test";
}
}
static final Callable<Foo> daggerSingletonFactory = new Callable<Foo>() {
final javax.inject.Provider<Foo> fooProvider;
{
ObjectGraph injector = ObjectGraph
.create(new DaggerSingletonFactoryModule());
ProviderHolder holder = new ProviderHolder();
injector.inject(holder);
fooProvider = holder.provider;
}
public Foo call() throws Exception {
return fooProvider.get();
}
};
static final Callable<Foo> juiceFactory = new Callable<Foo>() {
final Provider<Foo> fooProvider;
{
Injector injector;
try {
injector = Guice.createInjector(new AbstractModule() {
protected void configure() {
bind(Tee.class).to(TeeImpl.class);
bind(Bar.class).to(BarImpl.class);
bind(Foo.class).to(FooImpl.class);
bindConstant().annotatedWith(I.class).to(5);
bindConstant().annotatedWith(S.class).to("test");
}
});
} catch (CreationException e) {
throw new RuntimeException(e);
}
fooProvider = injector.getProvider(Foo.class);
}
public Foo call() throws Exception {
return fooProvider.get();
}
};
static final Callable<Foo> juiceSingletonFactory = new Callable<Foo>() {
final Provider<Foo> fooProvider;
{
Injector injector;
try {
injector = Guice.createInjector(new AbstractModule() {
protected void configure() {
bind(Tee.class).to(TeeImpl.class);
bind(Bar.class).to(BarImpl.class).in(Scopes.SINGLETON);
bind(Foo.class).to(FooSingletonImpl.class);
bindConstant().annotatedWith(I.class).to(5);
bindConstant().annotatedWith(S.class).to("test");
}
});
} catch (CreationException e) {
throw new RuntimeException(e);
}
fooProvider = injector.getProvider(Foo.class);
}
public Foo call() throws Exception {
return fooProvider.get();
}
};
private static class ByHandFactory implements Callable<Foo> {
private boolean isSingleton;
final Tee tee = new TeeImpl("test");
final Foo foo;
public ByHandFactory(boolean isSingleton) {
this.isSingleton = isSingleton;
foo = isSingleton ? createFoo() : null;
}
public Foo call() throws Exception {
if (isSingleton)
return foo;
else
return createFoo();
}
private Foo createFoo() {
FooImpl foo = new FooImpl();
foo.i = 5;
foo.s = "test";
Bar bar = new BarImpl(tee, 5);
Bar copy = isSingleton ? bar : new BarImpl(tee, 5);
foo.bar = bar;
foo.copy = copy;
return foo;
}
};
static final Callable<Foo> byHandFactory = new ByHandFactory(false);
static final Callable<Foo> byHandSingletonFactory = new ByHandFactory(true);
static void validate(Callable<Foo> t, boolean isSingleton) throws Exception {
Foo foo = t.call();
assertEquals(5, foo.getI());
assertEquals("test", foo.getS());
Bar bar = foo.getBar();
Bar copy = foo.getCopy();
assertSame(bar.getTee(), copy.getTee());
if (isSingleton) {
assertSame(bar, copy);
} else {
assertNotSame(bar, copy);
}
assertEquals(5, bar.getI());
assertEquals("test", bar.getTee().getS());
}
static final DecimalFormat format = new DecimalFormat();
static void iterate(Callable<Foo> callable, String label,
boolean isSingleton) {
iterate(callable, label, 1, isSingleton);
}
private static long concurrentTime = 0;
static void concurrentlyIterate(final Callable<Foo> callable, String label,
boolean isSingleton) {
iterate(callable, label, 5, isSingleton);
}
private static void iterate(final Callable<Foo> callable, String label,
int threadCount, final boolean isSingleton) {
final long count = isSingleton ? 100000 : 10000;
concurrentTime = 0;
Thread[] threads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
threads[i] = new Thread() {
public void run() {
long testStart = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
try {
validate(callable, isSingleton);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
synchronized (DaggerPerformanceTest.class) {
concurrentTime += (System.currentTimeMillis() - testStart);
}
}
};
}
for (int i = 0; i < threadCount; i++) {
threads[i].start();
}
for (int i = 0; i < threadCount; i++) {
try {
threads[i].join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
if (concurrentTime == 0) {
System.err.println(label + " is too freaking fast");
} else {
long total = count * threadCount * threadCount * 1000
/ concurrentTime;
System.err.println(label + format.format(total) + " creations/s");
}
}
public static interface Foo {
Bar getBar();
Bar getCopy();
String getS();
int getI();
}
public static class FooImpl implements Foo {
@Inject
Bar bar;
@Inject
Bar copy;
@Inject
@S
String s;
@Inject
@I
int i;
@Override
public Bar getBar() {
return bar;
}
@Override
public Bar getCopy() {
return copy;
}
@Override
public String getS() {
return s;
}
@Override
public int getI() {
return i;
}
}
@Singleton
public static class FooSingletonImpl implements Foo {
@Inject
Bar bar;
@Inject
Bar copy;
@Inject
@S
String s;
@Inject
@I
int i;
@Override
public Bar getBar() {
return bar;
}
@Override
public Bar getCopy() {
return copy;
}
@Override
public String getS() {
return s;
}
@Override
public int getI() {
return i;
}
}
interface Bar {
Tee getTee();
int getI();
}
public static class BarImpl implements Bar {
final int i;
final Tee tee;
@Inject
public BarImpl(Tee tee, @I int i) {
this.tee = tee;
this.i = i;
}
public Tee getTee() {
return tee;
}
public int getI() {
return i;
}
}
interface Tee {
String getS();
}
@Singleton
public static class TeeImpl implements Tee {
final String s;
@Inject
public TeeImpl(@S String s) {
this.s = s;
}
public String getS() {
return s;
}
}
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
@BindingAnnotation
@interface I {
}
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
@BindingAnnotation
@interface S {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment