PerformanceComparison.java revision c0c12ea61414709600577bb547e1e77b4a405691
166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee/**
266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * Copyright (C) 2006 Google Inc.
366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee *
466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * Licensed under the Apache License, Version 2.0 (the "License");
566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * you may not use this file except in compliance with the License.
666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * You may obtain a copy of the License at
766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee *
866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * http://www.apache.org/licenses/LICENSE-2.0
966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee *
1066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * Unless required by applicable law or agreed to in writing, software
1166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * distributed under the License is distributed on an "AS IS" BASIS,
1266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * See the License for the specific language governing permissions and
1466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * limitations under the License.
1566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee */
1666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
1766b415a2066cac9f36ed58070777de388f63a3a4crazybobleepackage com.google.inject;
1866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
19c0c12ea61414709600577bb547e1e77b4a405691kevinbimport java.lang.annotation.Retention;
20c0c12ea61414709600577bb547e1e77b4a405691kevinbimport static java.lang.annotation.RetentionPolicy.RUNTIME;
21c0c12ea61414709600577bb547e1e77b4a405691kevinbimport java.text.DecimalFormat;
22c0c12ea61414709600577bb547e1e77b4a405691kevinbimport java.util.concurrent.Callable;
236a565c7216be86b23ae7390febd6c1f061a3981fkevinbimport static junit.framework.Assert.assertEquals;
246a565c7216be86b23ae7390febd6c1f061a3981fkevinbimport static junit.framework.Assert.assertSame;
2566b415a2066cac9f36ed58070777de388f63a3a4crazybobleeimport org.springframework.beans.MutablePropertyValues;
2666b415a2066cac9f36ed58070777de388f63a3a4crazybobleeimport org.springframework.beans.factory.config.ConstructorArgumentValues;
2766b415a2066cac9f36ed58070777de388f63a3a4crazybobleeimport org.springframework.beans.factory.config.RuntimeBeanReference;
2866b415a2066cac9f36ed58070777de388f63a3a4crazybobleeimport org.springframework.beans.factory.support.DefaultListableBeanFactory;
2966b415a2066cac9f36ed58070777de388f63a3a4crazybobleeimport org.springframework.beans.factory.support.RootBeanDefinition;
3066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
3166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee/**
32e9f0fa57c4b41b803faa42273bd8697f531a5fb8crazyboblee * A semi-useless microbenchmark. Spring and Guice constuct the same object
33e9f0fa57c4b41b803faa42273bd8697f531a5fb8crazyboblee * graph a bunch of times, and we see who can construct the most per second.
34e9f0fa57c4b41b803faa42273bd8697f531a5fb8crazyboblee * As of this writing Guice is more than 50X faster. Also useful for comparing
35e9f0fa57c4b41b803faa42273bd8697f531a5fb8crazyboblee * pure Java configuration options.
3666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee *
3766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * @author crazybob@google.com (Bob Lee)
3866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee */
39041e93387a67a7d15330592077b08577b2961a2ecrazybobleepublic class PerformanceComparison {
4066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
41e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee  public static void main(String[] args) throws Exception {
42e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee    // Once warm up. Takes lazy loading out of the equation and ensures we
43e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee    // created the graphs properly.
44e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee    validate(springFactory);
45e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee    validate(juiceFactory);
46e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee    validate(byHandFactory);
47e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee
48e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee    for (int i2 = 0; i2 < 10; i2++) {
49e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee      iterate(springFactory, "Spring:  ");
50e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee      iterate(juiceFactory,  "Guice:   ");
51e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee      iterate(byHandFactory, "By Hand: ");
52e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee
53e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee      System.err.println();
54e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee    }
55e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee  }
56e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee
5766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee  static final Callable<Foo> springFactory = new Callable<Foo>() {
5866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
5966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    final DefaultListableBeanFactory beanFactory;
6066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
6166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    {
6266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      beanFactory = new DefaultListableBeanFactory();
6366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
6466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      RootBeanDefinition tee = new RootBeanDefinition(TeeImpl.class, true);
6566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      tee.setLazyInit(true);
6666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      ConstructorArgumentValues teeValues = new ConstructorArgumentValues();
6766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      teeValues.addGenericArgumentValue("test");
6866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      tee.setConstructorArgumentValues(teeValues);
6966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
7066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      RootBeanDefinition bar = new RootBeanDefinition(BarImpl.class, false);
7166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      ConstructorArgumentValues barValues = new ConstructorArgumentValues();
7266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      barValues.addGenericArgumentValue(new RuntimeBeanReference("tee"));
7366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      barValues.addGenericArgumentValue(5);
7466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      bar.setConstructorArgumentValues(barValues);
7566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
7666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      RootBeanDefinition foo = new RootBeanDefinition(Foo.class, false);
7766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      MutablePropertyValues fooValues = new MutablePropertyValues();
7866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      fooValues.addPropertyValue("i", 5);
7966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      fooValues.addPropertyValue("bar", new RuntimeBeanReference("bar"));
8066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      fooValues.addPropertyValue("copy", new RuntimeBeanReference("bar"));
8166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      fooValues.addPropertyValue("s", "test");
8266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      foo.setPropertyValues(fooValues);
8366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
8466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      beanFactory.registerBeanDefinition("foo", foo);
8566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      beanFactory.registerBeanDefinition("bar", bar);
8666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      beanFactory.registerBeanDefinition("tee", tee);
8766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    }
8866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
8966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    public Foo call() throws Exception {
9066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      return (Foo) beanFactory.getBean("foo");
9166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    }
9266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee  };
9366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
9466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee  static final Callable<Foo> juiceFactory = new Callable<Foo>() {
955746d5d7f2a97a9720ee33a7c7f9cc8e60e5cc71crazyboblee    final Locator<Foo> fooLocator;
967c5b2c4e5e3607c63c2785c8bc025706a158db80crazyboblee    {
977c5b2c4e5e3607c63c2785c8bc025706a158db80crazyboblee      ContainerBuilder builder = new ContainerBuilder();
98041e93387a67a7d15330592077b08577b2961a2ecrazyboblee
99a3796018ba672c1d7b9466ac2de1cf6d1f82a400crazyboblee      builder.install(new AbstractModule() {
100041e93387a67a7d15330592077b08577b2961a2ecrazyboblee        protected void configure() {
101e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee          bind(Tee.class).to(TeeImpl.class);
102041e93387a67a7d15330592077b08577b2961a2ecrazyboblee          bind(Bar.class).to(BarImpl.class);
103db178d7631170ba434558b5d07aeeffb846278a3crazyboblee          bind(Foo.class);
1041c4d3e37ba5aa517819f56e8544c4269b8ccadc3crazyboblee          bindConstant(I.class).to(5);
1051c4d3e37ba5aa517819f56e8544c4269b8ccadc3crazyboblee          bindConstant(S.class).to("test");
106041e93387a67a7d15330592077b08577b2961a2ecrazyboblee        }
107041e93387a67a7d15330592077b08577b2961a2ecrazyboblee      });
1087c5b2c4e5e3607c63c2785c8bc025706a158db80crazyboblee
1099bb62020927911172430dc3d94ee61796d519236crazyboblee      try {
1105746d5d7f2a97a9720ee33a7c7f9cc8e60e5cc71crazyboblee        fooLocator = builder.create().getLocator(Foo.class);
1115746d5d7f2a97a9720ee33a7c7f9cc8e60e5cc71crazyboblee      } catch (CreationException e) {
1129bb62020927911172430dc3d94ee61796d519236crazyboblee        throw new RuntimeException(e);
1139bb62020927911172430dc3d94ee61796d519236crazyboblee      }
1147c5b2c4e5e3607c63c2785c8bc025706a158db80crazyboblee    }
11566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
11666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    public Foo call() throws Exception {
1175746d5d7f2a97a9720ee33a7c7f9cc8e60e5cc71crazyboblee      return fooLocator.get();
11866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    }
11966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee  };
12066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
1219e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee  static final Callable<Foo> byHandFactory = new Callable<Foo>() {
1229e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee    final Tee tee = new TeeImpl("test");
1239e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee    public Foo call() throws Exception {
1249e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee      Foo foo = new Foo();
1259e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee      foo.setI(5);
1269e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee      foo.setS("test");
1279e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee      Bar bar = new BarImpl(tee, 5);
1289e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee      Bar copy = new BarImpl(tee, 5);
1299e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee      foo.setBar(bar);
1309e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee      foo.setCopy(copy);
1319e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee      return foo;
1329e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee    }
1339e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee  };
1349e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee
13566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee  static void validate(Callable<Foo> t) throws Exception {
13666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    Foo foo = t.call();
13766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    assertEquals(5, foo.i);
13866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    assertEquals("test", foo.s);
13966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    assertSame(foo.bar.getTee(), foo.copy.getTee());
14066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    assertEquals(5, foo.bar.getI());
14166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    assertEquals("test", foo.bar.getTee().getS());
14266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee  }
14366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
1446a565c7216be86b23ae7390febd6c1f061a3981fkevinb  static final DecimalFormat format = new DecimalFormat();
14566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
146041e93387a67a7d15330592077b08577b2961a2ecrazyboblee  static void iterate(Callable<Foo> callable, String label) throws Exception {
147041e93387a67a7d15330592077b08577b2961a2ecrazyboblee    int count = 100000;
148041e93387a67a7d15330592077b08577b2961a2ecrazyboblee    long time = System.currentTimeMillis();
149041e93387a67a7d15330592077b08577b2961a2ecrazyboblee    for (int i = 0; i < count; i++) {
150041e93387a67a7d15330592077b08577b2961a2ecrazyboblee      callable.call();
151041e93387a67a7d15330592077b08577b2961a2ecrazyboblee    }
152041e93387a67a7d15330592077b08577b2961a2ecrazyboblee    time = System.currentTimeMillis() - time;
153e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee    System.err.println(label
154e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee        + format.format(count * 1000 / time) + " creations/s");
155041e93387a67a7d15330592077b08577b2961a2ecrazyboblee  }
156041e93387a67a7d15330592077b08577b2961a2ecrazyboblee
15766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee  public static class Foo {
15866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
15966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    Bar bar;
16066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    Bar copy;
16166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    String s;
16266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    int i;
16366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
1644602a6fe08692b38cf36aa3cdb5c4e340e6929d7crazyboblee    @Inject
1651c4d3e37ba5aa517819f56e8544c4269b8ccadc3crazyboblee    public void setI(@I int i) {
16666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      this.i = i;
16766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    }
16866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
16966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    @Inject
17066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    public void setBar(Bar bar) {
17166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      this.bar = bar;
17266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    }
17366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
17466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    @Inject
17566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    public void setCopy(Bar copy) {
17666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      this.copy = copy;
17766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    }
17866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
1794602a6fe08692b38cf36aa3cdb5c4e340e6929d7crazyboblee    @Inject
1801c4d3e37ba5aa517819f56e8544c4269b8ccadc3crazyboblee    public void setS(@S String s) {
18166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      this.s = s;
18266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    }
18366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee  }
18466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
18566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee  interface Bar {
18666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
18766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    Tee getTee();
18866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    int getI();
18966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee  }
19066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
19166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee  public static class BarImpl implements Bar {
19266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
19366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    final int i;
19466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    final Tee tee;
19566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
19666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    @Inject
1971c4d3e37ba5aa517819f56e8544c4269b8ccadc3crazyboblee    public BarImpl(Tee tee, @I int i) {
19866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      this.tee = tee;
19966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      this.i = i;
20066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    }
20166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
20266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    public Tee getTee() {
20366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      return tee;
20466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    }
20566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
20666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    public int getI() {
20766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      return i;
20866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    }
20966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee  }
21066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
21166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee  interface Tee {
21266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
21366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    String getS();
21466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee  }
21566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
216e5fbbb0939eccd8e8dff78cd83cfb2f34ef2ed57crazyboblee  @ContainerScoped
21766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee  public static class TeeImpl implements Tee {
21866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
21966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    final String s;
22066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
22166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    @Inject
2221c4d3e37ba5aa517819f56e8544c4269b8ccadc3crazyboblee    public TeeImpl(@S String s) {
22366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      this.s = s;
22466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    }
22566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee
22666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    public String getS() {
22766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee      return s;
22866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee    }
22966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee  }
2301c4d3e37ba5aa517819f56e8544c4269b8ccadc3crazyboblee
2311c4d3e37ba5aa517819f56e8544c4269b8ccadc3crazyboblee  @Retention(RUNTIME)
232c0c12ea61414709600577bb547e1e77b4a405691kevinb  @BindingAnnotation @interface I {}
2331c4d3e37ba5aa517819f56e8544c4269b8ccadc3crazyboblee
2341c4d3e37ba5aa517819f56e8544c4269b8ccadc3crazyboblee  @Retention(RUNTIME)
235c0c12ea61414709600577bb547e1e77b4a405691kevinb  @BindingAnnotation @interface S {}
23666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee}
237