views:

377

answers:

11

Recently I got into a discussion with my Team lead about using temp variables vs calling getter methods. I was of the opinion for a long time that, if I know that I was going to have to call a simple getter method quite a number of times, I would put it into a temp variable and then use that variable instead. I thought that this would be a better both in terms of style and performance. However, my lead pointed out that in Java 4 and newer editions, this was not true somewhat. He is a believer of using a smaller variable space, so he told me that calling getter methods had a very negligible performance hit as opposed to using a temp variable, and hence using getters was better. However, I am not totally convinced by his argument. What do you guys think?

+13  A: 

Your lead is correct. In modern versions of the VM, simple getters that return a private field are inlined, meaning the performance overhead of a method call doesn't exist.

Randolpho
Erm, including non-final ones? How does the virtual machine know the referenced object is not of a subclass which has overridden the getter? Please provide a source for your claim. (To put in perspective, the few nano-seconds overhead of a function call hardly ever matters)
meriton
The VM will use profiling information to discover if the call to the property always ends up in the same place - see http://en.wikipedia.org/wiki/Inline_caching
Ben Lings
Inline caching is not done with profiling information - at least according to the article you linked. Even with such a technique, I think there will be an additional branch for the creation/testing of the inline cache, which is unnessessary for a field access.
meriton
@meriton: Perhaps I shouldn't have been so general. "simple getters are almost always inlined by the JIT compiler". Better? BTW, here's a research talk on the subject from Sun: http://research.sun.com/people/detlefs/talks/rice-98-talk/inline-talk.html. Note the date... summer, 98. This has been around for a decade.
Randolpho
+1: That was interesting reading, thank you. Still, it would be wrong to say that an inlined getter will be as fast as field access, because inlining of virtual methods requires an additional check (type, method or yet something else) at runtime. However, since the getter is called at least once in either approach presented the OP, and such checks are conceivably coalesced by the JIT, there should indeed be no performance difference at all.
meriton
And caching the variable locally will require a memory allocation. Do you really want to out-think the compiler when it's improving every year--and at a net cost, not gain in readability?
Bill K
I believe if you look at the byte code you will get stack allocation either way. Whether it is a fixed position on the stack or temporary stack to pass to the next thing... or just the increased stack usage form making extra get calls that might not be inlined. I think worrying about the performance of this is irrelevant in most cases, either way. Readability is the key and sometimes it is more readable to cache, and sometimes not. After all, it's better to call a method like getTheValueFromTheThingWithAReallyLongName() as few times as possible. ;)
PSpeed
@PSpeed: the bytecode may imply stack allocation, but the JIT compiler will (likely) inline the method invocation at runtime.
Randolpho
+3  A: 

I think that recent versions of the JVM are often sufficiently clever to cache the result of a function call automatically, if some conditions are met. I think the function must have no side effects and reliably return the same result every time it is called. Note that this may or may not be the case for simple getters, depending on what other code in your class is doing to the field values.

If this is not the case and the called function does significant processing then you would indeed be better of caching its result in a temporary variable. While the overhead of a call may be insignificant, a busy method will eat your lunch if you call it more often than necessary.

I also practice your style; even if not for performance reasons, I find my code more legible when it isn't full of cascades of function calls.

Carl Smotricz
Source? (How can the compiler determine that the method calls will always return the same result, i.e. that code executed in the mean time did not - directly or indirectly - modify the state accessed by the getter?)
meriton
+2  A: 

It depends. If you would like to make it clear that you use the same value again and again, I'd assign it to a temp variable. I'd do so if the call of the getter is somewhat lengthy, like myCustomObject.getASpecificValue().

You will get much fewer errors in your code if it is readable. So this is the main point.

The performance differences are very small or not existent.

tangens
+14  A: 

Never code for performance, always code for readability. Let the compiler do the work.

They can improve the compiler to run good code faster and suddenly your "Fast" code is actually slowing the system down.

Bill K
I can agree with this more. +100 Maintainability and legibility are far, far more important than performance.
Randolpho
Especially if the performance gain is measured in nano-seconds ...
meriton
+1, totally agreeing on that point
Willi
I agree with the spirit but not the letter of this. There are many things that go into performance; micro-optimizations are only a small part, and sometimes a necessary evil on performance-critical code. A good programmer chooses their algorithms and data-structures well as part of the planning, and SHOULD consider performance in general as part of the design process.
BobMcGee
@BobMcGee I agree completely--but I differentiate between "Programming" and "Optimizing". Doing an insertion sort into an array list when you have a linked list available is my optimal example of not actually knowing how to program.
Bill K
+2  A: 

If you keep the code evolution in mind, simple getters in v1.0 tend to become not-so-simple getters in v2.0.

The coder who changes a simple getter to not-so-simple getter usually has no clue that there is a function that calls this getter 10 times instead of 1 and never corrects it there, etc.

That's why from the point of view of the DRY principal it makes sense to cache value for repeated use.

Alexander Pogrebnyak
A: 

A general comment: In any modern system, except for I/O, do not worry about performance issues. Blazing fast CPUs and heaps of memory mean, all other issues are most of the time completely immaterial to actual performance of your system. [Of course, there are exceptions like caching solutions but they are far and rare.]

Now coming to this specific problem, yes, compiler will inline all the gets. Yet, even that is not the actual consideration, what should really matter is over all readability and flow of your code. Replacing indirections by a local variable is better, if the call used multiple times, like customer.gerOrder().getAddress() is better captured in local variable.

I disagree STRONGLY. Yes, a good compiler will handle the small details, but totally ignoring questions of implementation efficiency is the sign of a lazy programmer. You can make an application unusably slow by choosing an O(n^2) algorithm where an O(n log n) one works, or forcing a lot of un-necessary string parsing (*cough* XML *cough*).
BobMcGee
+5  A: 

Don't forget that by assigning the value of getSomething() to a variable rather than calling it twice, you are assuming that getSomething() would have returned the same thing the second time you called it. Perhaps that's a valid assumption in the scenario you are talking about, but there are times when it isn't.

Paul Clapham
A: 

The virtual machine can handle the first four local variables more efficiently than any local variable declared after that (see lload and lload_<n> instructions). So caching the result of the (inlined) getter may actually hurt your performance.

Of course on their own either performance influence is almost negligible so if you want to optimize your code make sure that you are really tackling an actual bottleneck!

Bombe
A: 

Another reason to not use a temporary variable to contain the result of a method call is that using the method you get the most updated value. This could not be a problem with the actual code, but it could become a problem when the code is changed.

kiamlaluno
Using the latest value may also be a problem, if you've just stepped into a block of code based on the evaluation of the previous getter.And now you want to do something to that value that you've just checked ... but it has changed.
crowne
+1  A: 

I will not sacrifice "Code readability" to some microseconds.
Perhaps it is true that getter performs better and can save you several microseconds in runtime. But i believe, variables can save you several hours or perhaps days when bug fixing time comes.

Sorry for the non-technical answer.

Hendra Jaya
A: 

It is not worth if it is just getFoo(). By caching it into a temp variable you are not making it much faster and maybe asking for trouble because getFoo() may return different value later. But if it is something like getFoo().getBar().getBaz().getSomething() and you know the value will not be changed within the block of code, then there may be a reason to use temp variable for better readability.

fastcodejava