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 17 package com.google.inject; 18 19 import static java.lang.annotation.RetentionPolicy.RUNTIME; 20 import static junit.framework.Assert.assertEquals; 21 import static junit.framework.Assert.assertSame; 22 23 import java.lang.annotation.Retention; 24 import java.text.DecimalFormat; 25 import java.util.concurrent.Callable; 26 import org.springframework.beans.MutablePropertyValues; 27 import org.springframework.beans.factory.config.ConstructorArgumentValues; 28 import org.springframework.beans.factory.config.RuntimeBeanReference; 29 import org.springframework.beans.factory.support.DefaultListableBeanFactory; 30 import org.springframework.beans.factory.support.RootBeanDefinition; 31 32 /** 33 * A semi-useless microbenchmark. Spring and Guice constuct the same object graph a bunch of times, 34 * and we see who can construct the most per second. As of this writing Guice is more than 50X 35 * faster. Also useful for comparing pure Java configuration options. 36 * 37 * @author crazybob@google.com (Bob Lee) 38 */ 39 public class PerformanceComparison { 40 main(String[] args)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 System.err.println("Concurrent:"); 57 58 for (int i2 = 0; i2 < 10; i2++) { 59 concurrentlyIterate(springFactory, "Spring: "); 60 concurrentlyIterate(juiceFactory, "Guice: "); 61 concurrentlyIterate(byHandFactory, "By Hand: "); 62 63 System.err.println(); 64 } 65 } 66 67 static final Callable<Foo> springFactory = 68 new Callable<Foo>() { 69 70 final DefaultListableBeanFactory beanFactory; 71 72 { 73 beanFactory = new DefaultListableBeanFactory(); 74 75 RootBeanDefinition tee = new RootBeanDefinition(TeeImpl.class, true); 76 tee.setLazyInit(true); 77 ConstructorArgumentValues teeValues = new ConstructorArgumentValues(); 78 teeValues.addGenericArgumentValue("test"); 79 tee.setConstructorArgumentValues(teeValues); 80 81 RootBeanDefinition bar = new RootBeanDefinition(BarImpl.class, false); 82 ConstructorArgumentValues barValues = new ConstructorArgumentValues(); 83 barValues.addGenericArgumentValue(new RuntimeBeanReference("tee")); 84 barValues.addGenericArgumentValue(5); 85 bar.setConstructorArgumentValues(barValues); 86 87 RootBeanDefinition foo = new RootBeanDefinition(Foo.class, false); 88 MutablePropertyValues fooValues = new MutablePropertyValues(); 89 fooValues.addPropertyValue("i", 5); 90 fooValues.addPropertyValue("bar", new RuntimeBeanReference("bar")); 91 fooValues.addPropertyValue("copy", new RuntimeBeanReference("bar")); 92 fooValues.addPropertyValue("s", "test"); 93 foo.setPropertyValues(fooValues); 94 95 beanFactory.registerBeanDefinition("foo", foo); 96 beanFactory.registerBeanDefinition("bar", bar); 97 beanFactory.registerBeanDefinition("tee", tee); 98 } 99 100 @Override 101 public Foo call() throws Exception { 102 return (Foo) beanFactory.getBean("foo"); 103 } 104 }; 105 106 static final Callable<Foo> juiceFactory = 107 new Callable<Foo>() { 108 final Provider<Foo> fooProvider; 109 110 { 111 Injector injector; 112 try { 113 injector = 114 Guice.createInjector( 115 new AbstractModule() { 116 @Override 117 protected void configure() { 118 bind(Tee.class).to(TeeImpl.class); 119 bind(Bar.class).to(BarImpl.class); 120 bind(Foo.class); 121 bindConstant().annotatedWith(I.class).to(5); 122 bindConstant().annotatedWith(S.class).to("test"); 123 } 124 }); 125 } catch (CreationException e) { 126 throw new RuntimeException(e); 127 } 128 fooProvider = injector.getProvider(Foo.class); 129 } 130 131 @Override 132 public Foo call() throws Exception { 133 return fooProvider.get(); 134 } 135 }; 136 137 static final Callable<Foo> byHandFactory = 138 new Callable<Foo>() { 139 final Tee tee = new TeeImpl("test"); 140 141 @Override 142 public Foo call() throws Exception { 143 Foo foo = new Foo(); 144 foo.setI(5); 145 foo.setS("test"); 146 Bar bar = new BarImpl(tee, 5); 147 Bar copy = new BarImpl(tee, 5); 148 foo.setBar(bar); 149 foo.setCopy(copy); 150 return foo; 151 } 152 }; 153 validate(Callable<Foo> t)154 static void validate(Callable<Foo> t) throws Exception { 155 Foo foo = t.call(); 156 assertEquals(5, foo.i); 157 assertEquals("test", foo.s); 158 assertSame(foo.bar.getTee(), foo.copy.getTee()); 159 assertEquals(5, foo.bar.getI()); 160 assertEquals("test", foo.bar.getTee().getS()); 161 } 162 163 static final DecimalFormat format = new DecimalFormat(); 164 iterate(Callable<Foo> callable, String label)165 static void iterate(Callable<Foo> callable, String label) { 166 int count = 100000; 167 168 long time = System.currentTimeMillis(); 169 170 for (int i = 0; i < count; i++) { 171 try { 172 callable.call(); 173 } catch (Exception e) { 174 throw new RuntimeException(e); 175 } 176 } 177 178 time = System.currentTimeMillis() - time; 179 180 System.err.println(label + format.format(count * 1000 / time) + " creations/s"); 181 } 182 concurrentlyIterate(final Callable<Foo> callable, String label)183 static void concurrentlyIterate(final Callable<Foo> callable, String label) { 184 int threadCount = 10; 185 final int count = 10000; 186 187 Thread[] threads = new Thread[threadCount]; 188 189 for (int i = 0; i < threadCount; i++) { 190 threads[i] = 191 new Thread() { 192 @Override 193 public void run() { 194 for (int i = 0; i < count; i++) { 195 try { 196 validate(callable); 197 } catch (Exception e) { 198 throw new RuntimeException(e); 199 } 200 } 201 } 202 }; 203 } 204 205 long time = System.currentTimeMillis(); 206 207 for (int i = 0; i < threadCount; i++) { 208 threads[i].start(); 209 } 210 211 for (int i = 0; i < threadCount; i++) { 212 try { 213 threads[i].join(); 214 } catch (InterruptedException e) { 215 throw new RuntimeException(e); 216 } 217 } 218 219 time = System.currentTimeMillis() - time; 220 221 System.err.println(label + format.format(count * 1000 / time) + " creations/s"); 222 } 223 224 public static class Foo { 225 226 Bar bar; 227 Bar copy; 228 String s; 229 int i; 230 231 @Inject setI(@ int i)232 public void setI(@I int i) { 233 this.i = i; 234 } 235 236 @Inject setBar(Bar bar)237 public void setBar(Bar bar) { 238 this.bar = bar; 239 } 240 241 @Inject setCopy(Bar copy)242 public void setCopy(Bar copy) { 243 this.copy = copy; 244 } 245 246 @Inject setS(@ String s)247 public void setS(@S String s) { 248 this.s = s; 249 } 250 } 251 252 interface Bar { 253 getTee()254 Tee getTee(); 255 getI()256 int getI(); 257 } 258 259 public static class BarImpl implements Bar { 260 261 final int i; 262 final Tee tee; 263 264 @Inject BarImpl(Tee tee, @I int i)265 public BarImpl(Tee tee, @I int i) { 266 this.tee = tee; 267 this.i = i; 268 } 269 270 @Override getTee()271 public Tee getTee() { 272 return tee; 273 } 274 275 @Override getI()276 public int getI() { 277 return i; 278 } 279 } 280 281 interface Tee { 282 getS()283 String getS(); 284 } 285 286 @Singleton 287 public static class TeeImpl implements Tee { 288 289 final String s; 290 291 @Inject TeeImpl(@ String s)292 public TeeImpl(@S String s) { 293 this.s = s; 294 } 295 296 @Override getS()297 public String getS() { 298 return s; 299 } 300 } 301 302 @Retention(RUNTIME) 303 @BindingAnnotation 304 @interface I {} 305 306 @Retention(RUNTIME) 307 @BindingAnnotation 308 @interface S {} 309 } 310