001: /**
002: * Copyright (C) 2006 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */package com.google.inject;
016:
017: import java.lang.annotation.Retention;
018: import static java.lang.annotation.RetentionPolicy.RUNTIME;
019: import java.text.DecimalFormat;
020: import java.util.concurrent.Callable;
021: import static junit.framework.Assert.assertEquals;
022: import static junit.framework.Assert.assertSame;
023: import org.springframework.beans.MutablePropertyValues;
024: import org.springframework.beans.factory.config.ConstructorArgumentValues;
025: import org.springframework.beans.factory.config.RuntimeBeanReference;
026: import org.springframework.beans.factory.support.DefaultListableBeanFactory;
027: import org.springframework.beans.factory.support.RootBeanDefinition;
028:
029: /**
030: * A semi-useless microbenchmark. Spring and Guice constuct the same object
031: * graph a bunch of times, and we see who can construct the most per second.
032: * As of this writing Guice is more than 50X faster. Also useful for comparing
033: * pure Java configuration options.
034: *
035: * @author crazybob@google.com (Bob Lee)
036: */
037: public class PerformanceComparison {
038:
039: public static void main(String[] args) throws Exception {
040: // Once warm up. Takes lazy loading out of the equation and ensures we
041: // created the graphs properly.
042: validate(springFactory);
043: validate(juiceFactory);
044: validate(byHandFactory);
045:
046: for (int i2 = 0; i2 < 10; i2++) {
047: iterate(springFactory, "Spring: ");
048: iterate(juiceFactory, "Guice: ");
049: iterate(byHandFactory, "By Hand: ");
050:
051: System.err.println();
052: }
053: }
054:
055: static final Callable<Foo> springFactory = new Callable<Foo>() {
056:
057: final DefaultListableBeanFactory beanFactory;
058:
059: {
060: beanFactory = new DefaultListableBeanFactory();
061:
062: RootBeanDefinition tee = new RootBeanDefinition(
063: TeeImpl.class, true);
064: tee.setLazyInit(true);
065: ConstructorArgumentValues teeValues = new ConstructorArgumentValues();
066: teeValues.addGenericArgumentValue("test");
067: tee.setConstructorArgumentValues(teeValues);
068:
069: RootBeanDefinition bar = new RootBeanDefinition(
070: BarImpl.class, false);
071: ConstructorArgumentValues barValues = new ConstructorArgumentValues();
072: barValues.addGenericArgumentValue(new RuntimeBeanReference(
073: "tee"));
074: barValues.addGenericArgumentValue(5);
075: bar.setConstructorArgumentValues(barValues);
076:
077: RootBeanDefinition foo = new RootBeanDefinition(Foo.class,
078: false);
079: MutablePropertyValues fooValues = new MutablePropertyValues();
080: fooValues.addPropertyValue("i", 5);
081: fooValues.addPropertyValue("bar", new RuntimeBeanReference(
082: "bar"));
083: fooValues.addPropertyValue("copy",
084: new RuntimeBeanReference("bar"));
085: fooValues.addPropertyValue("s", "test");
086: foo.setPropertyValues(fooValues);
087:
088: beanFactory.registerBeanDefinition("foo", foo);
089: beanFactory.registerBeanDefinition("bar", bar);
090: beanFactory.registerBeanDefinition("tee", tee);
091: }
092:
093: public Foo call() throws Exception {
094: return (Foo) beanFactory.getBean("foo");
095: }
096: };
097:
098: static final Callable<Foo> juiceFactory = new Callable<Foo>() {
099: final Provider<Foo> fooProvider;
100: {
101: Injector injector;
102: try {
103: injector = Guice.createInjector(new AbstractModule() {
104: protected void configure() {
105: bind(Tee.class).to(TeeImpl.class);
106: bind(Bar.class).to(BarImpl.class);
107: bind(Foo.class);
108: bindConstant().annotatedWith(I.class).to(5);
109: bindConstant().annotatedWith(S.class)
110: .to("test");
111: }
112: });
113: } catch (CreationException e) {
114: throw new RuntimeException(e);
115: }
116: fooProvider = injector.getProvider(Foo.class);
117: }
118:
119: public Foo call() throws Exception {
120: return fooProvider.get();
121: }
122: };
123:
124: static final Callable<Foo> byHandFactory = new Callable<Foo>() {
125: final Tee tee = new TeeImpl("test");
126:
127: public Foo call() throws Exception {
128: Foo foo = new Foo();
129: foo.setI(5);
130: foo.setS("test");
131: Bar bar = new BarImpl(tee, 5);
132: Bar copy = new BarImpl(tee, 5);
133: foo.setBar(bar);
134: foo.setCopy(copy);
135: return foo;
136: }
137: };
138:
139: static void validate(Callable<Foo> t) throws Exception {
140: Foo foo = t.call();
141: assertEquals(5, foo.i);
142: assertEquals("test", foo.s);
143: assertSame(foo.bar.getTee(), foo.copy.getTee());
144: assertEquals(5, foo.bar.getI());
145: assertEquals("test", foo.bar.getTee().getS());
146: }
147:
148: static final DecimalFormat format = new DecimalFormat();
149:
150: static void iterate(Callable<Foo> callable, String label)
151: throws Exception {
152: int count = 100000;
153: long time = System.currentTimeMillis();
154: for (int i = 0; i < count; i++) {
155: callable.call();
156: }
157: time = System.currentTimeMillis() - time;
158: System.err.println(label + format.format(count * 1000 / time)
159: + " creations/s");
160: }
161:
162: public static class Foo {
163:
164: Bar bar;
165: Bar copy;
166: String s;
167: int i;
168:
169: @Inject
170: public void setI(@I
171: int i) {
172: this .i = i;
173: }
174:
175: @Inject
176: public void setBar(Bar bar) {
177: this .bar = bar;
178: }
179:
180: @Inject
181: public void setCopy(Bar copy) {
182: this .copy = copy;
183: }
184:
185: @Inject
186: public void setS(@S
187: String s) {
188: this .s = s;
189: }
190: }
191:
192: interface Bar {
193:
194: Tee getTee();
195:
196: int getI();
197: }
198:
199: public static class BarImpl implements Bar {
200:
201: final int i;
202: final Tee tee;
203:
204: @Inject
205: public BarImpl(Tee tee, @I
206: int i) {
207: this .tee = tee;
208: this .i = i;
209: }
210:
211: public Tee getTee() {
212: return tee;
213: }
214:
215: public int getI() {
216: return i;
217: }
218: }
219:
220: interface Tee {
221:
222: String getS();
223: }
224:
225: @Singleton
226: public static class TeeImpl implements Tee {
227:
228: final String s;
229:
230: @Inject
231: public TeeImpl(@S
232: String s) {
233: this .s = s;
234: }
235:
236: public String getS() {
237: return s;
238: }
239: }
240:
241: @Retention(RUNTIME)
242: @BindingAnnotation
243: @interface I {
244: }
245:
246: @Retention(RUNTIME)
247: @BindingAnnotation
248: @interface S {
249: }
250: }
|