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