Reputation: 1581
In Java, is there a performance hit if i continually use nested get to retrieve values? For instance:
String firstname = getOffice().getDepartment().getEmployee().getFirstName();
String lastname = getOffice().getDepartment().getEmployee().getLastName();
String address = getOffice().getDepartment().getEmployee().getAddress();
VS:
Employee e = getOffice().getDepartment().getEmployee();
String firstname = e.getFirstName();
String lastname = e.getLastName();
String address = e.getAddress();
Would the 2nd version be faster because it has less 'jumps'?
Upvotes: 3
Views: 136
Reputation: 2132
Either use byte code analysis or time the two approaches using System.nanoTime
. I think second one is faster. here is what I did to conclude this:
I wrote three classes as given below:
public static class A {
public B b = new B();
}
public static class B {
public E e = new E();
}
public static class E {
public String name = "s";
public int age = 1;
}
Then I wrote two simple methods and get their java byte code using javap -c CLASS_NAME
.
public static void Test1() {
A a = new A();
String str = a.b.e.name;
int age = a.b.e.age;
}
The byte code of above method is:
public static void Test1();
Code:
// new A();
0: new #15
3: dup
4: invokespecial #17
7: astore_0
8: aload_0
// a.b (it accesses the field and put it on operand stack)
9: getfield #18
// b.e
12: getfield #22
// b.name
15: getfield #28
// pop 'name' from stack
18: astore_1
19: aload_0
// cyle continues
20: getfield #18
23: getfield #22
26: getfield #34
29: istore_2
30: return
You can clearly see at byte code level, each time you try to access field, it put the value of that filed on stack and then this cycle continues. Therefore, a.a1.a2....an
would be n
instruction if stack would have enough spae to hold all n
. And there was no optimisation by compiler this same cycle of called again to access both name
and age
field.
Now here is the second method:
public static void Test2() {
A a = new A();
E e = a.b.e;
String str = e.name;
int age = e.age;
}
Byte code for above method is:
public static void Test2();
Code:
// new A();
0: new #15
3: dup
4: invokespecial #17
7: astore_0
8: aload_0
// store a.b.e on operand stack once
9: getfield #18
12: getfield #22
15: astore_1
16: aload_1
// get 'name' field
17: getfield #28
20: astore_2
21: aload_1
// get 'age' field
22: getfield #34
25: istore_3
26: return
Above is 4 instruction shorter than previous code as it prevents execution of getfield
. So I think this should be faster than previous one.
Upvotes: 0
Reputation: 29166
The optimization you are thinking about is called premature optimization. You should not think about these unless you really have to.
I agree with @AmitD's answer about being the second one more readable. When chaining method calls like this, you can also write them in the following way -
Employee e = getOffice()
.getDepartment()
.getEmployee();
String firstname = e.getFirstName();
String lastname = e.getLastName();
String address = e.getAddress();
to further improve readability.
Upvotes: 2
Reputation: 81882
Possibly yes. But assuming the getters look like ordinary getters on the inside it will probably be so small that it becomes almost impossible to measure.
Also if you run through this code often enough to make it matter, the magic of the Hotspot compiler will kick in and mangle the byte code, probably again making both variations the same.
In the end it is extremely hard to tell what really will happen. If performance matters for you set up a test. If performance doesn't matter enough to justify the costs of the test ... well then it doesn't matter enough to worry.
Upvotes: 0
Reputation: 1074198
It depends entirely on what the getXYZ
calls do. If they're simple accessors to an underlying field, then no, not on HotSpot (Oracle's JVM), because they'll get optimized out if there's any need to do so. If, on the other hand, they do any kind of complex work (traversing a btree, etc.), then of course they'll have to do that work repeatedly (unless HotSpot can prove to itself that the calls are idempotent, which if the code has any complexity becomes unlikely). (Whether it matters that they do the work repeatedly is another question; until/unless you see an actual performance problem, don't worry about it.)
But the second is much more readable and maintainable. That's the more powerful reason for using it.
Upvotes: 9
Reputation: 19185
Rather than performance I see second as better human understandable code
. You should not worry about micro optimizations but write a good and clean code.
Upvotes: 4