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