Comment #2 on issue 572 by [email protected]: Performance problem or wrong
usage?
http://code.google.com/p/google-guice/issues/detail?id=572
Hello Mcculls,
thanks for the quick response (sorry, my english is not the best, but I
hope you can understand).
- I see: I'm not only a beginner with DI/Guice, also in Java.
- I was aware, that my test (with all the commented lines (//)) only
measure the creation time of a object.
And the a compiler can optimize many things (drop unused object etc).
I was not aware about the JIT optimization, which maybe infects the
measurements.
- I was aware, that Guice must be slower than pure "new" operations and
uses "reflection".
- As longer I use an object the lesser the overhead of the creation is.
- So you are right: I must see both, the creation and the usage of an
object.
- I was aware, after the "wiring", the rest of the code has the same
performance (usage of the object).
- I agree now: I can't see the creation isolated from the usage.
My second test (see below - I'm sure this test is not perfect) will do now
some more steps
with the created person, so the person will be used (getter/setter). (Plus
other stuff like string concatination).
- Now the ratio between creation/usage is much better
- Now the ratio between the classic way and Guice is much better and the
overhead is acceptable.
- I don't worry about an application is 10% - 50% slower, but 50 times is
too much, so I was confused
Here the result from the test:
(Measurement is now in nanosec, only the output is in millisec)
T = totalTime
C = creationTime (accumulated)
U = usageTime (accumulated)
testClassicWay Iter: 1000000 C: 1225ms U: 2182ms T: 5863ms C/U 0,562
C/T: 0,209
testGuiceSimple Iter: 1000000 C: 2086ms U: 2125ms T: 6614ms C/U 0,981
C/T: 0,315
Classic/Guice: 0,887 - Guice/Classic: 1,128
Person Instances created: 2000000
Thanks for your help, I will give Guice now a chance :-)
Uwe
---
package sandbox.guice.performance;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.google.inject.Binder;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.internal.cglib.proxy.Factory;
public class PerfTest {
static private final long max = 1000000;
static private long testClassicWay = 0;
static private long testGuiceSimple = 0;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
System.out.println("T = totalTime");
System.out.println("C = creationTime (accumulated)");
System.out.println("U = usageTime (accumulated)");
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
System.out.format("Classic/Guice: %s - Guice/Classic: %s\n",
factor(testClassicWay, testGuiceSimple), factor(testGuiceSimple,
testClassicWay));
System.out.println("Person Instances created: " +
RealPerson.personInstances);
assertEquals(max * 2, RealPerson.personInstances);
}
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
static interface Person {
public abstract String getFirstName();
public abstract void setFirstName(String firstName);
public abstract String getLastName();
public abstract void setLastName(String lastName);
}
static class RealPerson implements Person {
static int personInstances = 0; // to see, that person is
really created
private String firstName;
private String lastName;
public RealPerson () {
personInstances++;
}
@Override
public String getFirstName() {
return firstName;
}
@Override
public void setFirstName(String firstName) {
this.firstName = firstName;
}
@Override
public String getLastName() {
return lastName;
}
@Override
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
static abstract class PersonFactory {
public static Person createPerson() {return new RealPerson();}
}
static abstract class
PersonFactoryWrapperToBeMoreExpensiveForTheClassicWay extends PersonFactory
{
public static Person createPerson() {return
PersonFactory.createPerson();}
}
static private String time (long t) {
return "" + (t / 1000000) + "ms";
}
static private String factor(double a, double b) {
return String.format("%.3f", a / b);
}
public void usePerson (Person person, long i) throws Exception {
person.setFirstName("Guice" +i);
person.setLastName("Google" +i);
assertEquals(RealPerson.class, person.getClass());
assertEquals("Guice" +i, person.getFirstName());
assertEquals("Google" +i, person.getLastName());
}
@Test
public void testClassicWay () throws Exception {
long t1 = System.nanoTime();
long creationTime = 0;
long usageTime = 0;
for (long i = 0; i < max; i++) {
long c1, c2;
c1 = System.nanoTime();
Person person =
PersonFactoryWrapperToBeMoreExpensiveForTheClassicWay.createPerson();
c2 = System.nanoTime();
creationTime += c2 - c1;
c1 = System.nanoTime();
usePerson(person, i);
c2 = System.nanoTime();
usageTime += (c2 - c1);
}
long t2 = System.nanoTime();
long totalTime = t2 - t1;
testClassicWay = totalTime;
System.out.format("%-20s Iter: %6d C: %s U: %s T: %s C/U %s C/T:
%s\n",
Thread.currentThread().getStackTrace()[1].getMethodName(), max,
time(creationTime), time(usageTime), time(t2-t1), factor (creationTime,
usageTime), factor (creationTime, totalTime));
}
@Test
public void testGuiceSimple () throws Exception {
Injector injector = Guice.createInjector(new Module() {
@Override
public void configure(Binder binder) {
binder.bind(Person.class).to(RealPerson.class);
}
});
long t1 = System.nanoTime();
long creationTime = 0;
long usageTime = 0;
for (long i = 0; i < max; i++) {
long c1, c2;
c1 = System.nanoTime();
Person person = injector.getInstance(Person.class);
c2 = System.nanoTime();
creationTime += c2 - c1;
c1 = System.nanoTime();
usePerson(person, i);
c2 = System.nanoTime();
usageTime += (c2 - c1);
}
long t2 = System.nanoTime();
long totalTime = t2 - t1;
testGuiceSimple = totalTime;
System.out.format("%-20s Iter: %6d C: %s U: %s T: %s C/U %s C/T:
%s\n",
Thread.currentThread().getStackTrace()[1].getMethodName(), max,
time(creationTime), time(usageTime), time(t2-t1), factor (creationTime,
usageTime), factor (creationTime, totalTime));
}
}
--
You received this message because you are subscribed to the Google Groups
"google-guice-dev" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/google-guice-dev?hl=en.