PerformanceComparison.java revision c0c12ea61414709600577bb547e1e77b4a405691
1/**
2 * Copyright (C) 2006 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.inject;
18
19import java.lang.annotation.Retention;
20import static java.lang.annotation.RetentionPolicy.RUNTIME;
21import java.text.DecimalFormat;
22import java.util.concurrent.Callable;
23import static junit.framework.Assert.assertEquals;
24import static junit.framework.Assert.assertSame;
25import org.springframework.beans.MutablePropertyValues;
26import org.springframework.beans.factory.config.ConstructorArgumentValues;
27import org.springframework.beans.factory.config.RuntimeBeanReference;
28import org.springframework.beans.factory.support.DefaultListableBeanFactory;
29import org.springframework.beans.factory.support.RootBeanDefinition;
30
31/**
32 * A semi-useless microbenchmark. Spring and Guice constuct the same object
33 * graph a bunch of times, and we see who can construct the most per second.
34 * As of this writing Guice is more than 50X faster. Also useful for comparing
35 * pure Java configuration options.
36 *
37 * @author crazybob@google.com (Bob Lee)
38 */
39public class PerformanceComparison {
40
41  public static void main(String[] args) throws Exception {
42    // Once warm up. Takes lazy loading out of the equation and ensures we
43    // created the graphs properly.
44    validate(springFactory);
45    validate(juiceFactory);
46    validate(byHandFactory);
47
48    for (int i2 = 0; i2 < 10; i2++) {
49      iterate(springFactory, "Spring:  ");
50      iterate(juiceFactory,  "Guice:   ");
51      iterate(byHandFactory, "By Hand: ");
52
53      System.err.println();
54    }
55  }
56
57  static final Callable<Foo> springFactory = new Callable<Foo>() {
58
59    final DefaultListableBeanFactory beanFactory;
60
61    {
62      beanFactory = new DefaultListableBeanFactory();
63
64      RootBeanDefinition tee = new RootBeanDefinition(TeeImpl.class, true);
65      tee.setLazyInit(true);
66      ConstructorArgumentValues teeValues = new ConstructorArgumentValues();
67      teeValues.addGenericArgumentValue("test");
68      tee.setConstructorArgumentValues(teeValues);
69
70      RootBeanDefinition bar = new RootBeanDefinition(BarImpl.class, false);
71      ConstructorArgumentValues barValues = new ConstructorArgumentValues();
72      barValues.addGenericArgumentValue(new RuntimeBeanReference("tee"));
73      barValues.addGenericArgumentValue(5);
74      bar.setConstructorArgumentValues(barValues);
75
76      RootBeanDefinition foo = new RootBeanDefinition(Foo.class, false);
77      MutablePropertyValues fooValues = new MutablePropertyValues();
78      fooValues.addPropertyValue("i", 5);
79      fooValues.addPropertyValue("bar", new RuntimeBeanReference("bar"));
80      fooValues.addPropertyValue("copy", new RuntimeBeanReference("bar"));
81      fooValues.addPropertyValue("s", "test");
82      foo.setPropertyValues(fooValues);
83
84      beanFactory.registerBeanDefinition("foo", foo);
85      beanFactory.registerBeanDefinition("bar", bar);
86      beanFactory.registerBeanDefinition("tee", tee);
87    }
88
89    public Foo call() throws Exception {
90      return (Foo) beanFactory.getBean("foo");
91    }
92  };
93
94  static final Callable<Foo> juiceFactory = new Callable<Foo>() {
95    final Locator<Foo> fooLocator;
96    {
97      ContainerBuilder builder = new ContainerBuilder();
98
99      builder.install(new AbstractModule() {
100        protected void configure() {
101          bind(Tee.class).to(TeeImpl.class);
102          bind(Bar.class).to(BarImpl.class);
103          bind(Foo.class);
104          bindConstant(I.class).to(5);
105          bindConstant(S.class).to("test");
106        }
107      });
108
109      try {
110        fooLocator = builder.create().getLocator(Foo.class);
111      } catch (CreationException e) {
112        throw new RuntimeException(e);
113      }
114    }
115
116    public Foo call() throws Exception {
117      return fooLocator.get();
118    }
119  };
120
121  static final Callable<Foo> byHandFactory = new Callable<Foo>() {
122    final Tee tee = new TeeImpl("test");
123    public Foo call() throws Exception {
124      Foo foo = new Foo();
125      foo.setI(5);
126      foo.setS("test");
127      Bar bar = new BarImpl(tee, 5);
128      Bar copy = new BarImpl(tee, 5);
129      foo.setBar(bar);
130      foo.setCopy(copy);
131      return foo;
132    }
133  };
134
135  static void validate(Callable<Foo> t) throws Exception {
136    Foo foo = t.call();
137    assertEquals(5, foo.i);
138    assertEquals("test", foo.s);
139    assertSame(foo.bar.getTee(), foo.copy.getTee());
140    assertEquals(5, foo.bar.getI());
141    assertEquals("test", foo.bar.getTee().getS());
142  }
143
144  static final DecimalFormat format = new DecimalFormat();
145
146  static void iterate(Callable<Foo> callable, String label) throws Exception {
147    int count = 100000;
148    long time = System.currentTimeMillis();
149    for (int i = 0; i < count; i++) {
150      callable.call();
151    }
152    time = System.currentTimeMillis() - time;
153    System.err.println(label
154        + format.format(count * 1000 / time) + " creations/s");
155  }
156
157  public static class Foo {
158
159    Bar bar;
160    Bar copy;
161    String s;
162    int i;
163
164    @Inject
165    public void setI(@I int i) {
166      this.i = i;
167    }
168
169    @Inject
170    public void setBar(Bar bar) {
171      this.bar = bar;
172    }
173
174    @Inject
175    public void setCopy(Bar copy) {
176      this.copy = copy;
177    }
178
179    @Inject
180    public void setS(@S String s) {
181      this.s = s;
182    }
183  }
184
185  interface Bar {
186
187    Tee getTee();
188    int getI();
189  }
190
191  public static class BarImpl implements Bar {
192
193    final int i;
194    final Tee tee;
195
196    @Inject
197    public BarImpl(Tee tee, @I int i) {
198      this.tee = tee;
199      this.i = i;
200    }
201
202    public Tee getTee() {
203      return tee;
204    }
205
206    public int getI() {
207      return i;
208    }
209  }
210
211  interface Tee {
212
213    String getS();
214  }
215
216  @ContainerScoped
217  public static class TeeImpl implements Tee {
218
219    final String s;
220
221    @Inject
222    public TeeImpl(@S String s) {
223      this.s = s;
224    }
225
226    public String getS() {
227      return s;
228    }
229  }
230
231  @Retention(RUNTIME)
232  @BindingAnnotation @interface I {}
233
234  @Retention(RUNTIME)
235  @BindingAnnotation @interface S {}
236}
237