12

I have a for loop which runs 4096 times and it should be as fast as possible. Performance is really important here. Currently I use getter methods inside the loop which just return values or objects from fields which don't change while the loop is in progress.

Example:

for (;;) {
    doSomething(example.getValue());
}

Is there any overhead using getters? Is it faster using the following way?

Example:

Object object = example.getValue();
for (;;) {
    doSomething(object);
}

If yes, is that also true for accessing public fields like example.value?

Edit: I don't use System.out.println() inside the loop.

Edit: Some fields are not final. No fields are volatile and no method (getter) is synchronized.

stonar96
  • 1,359
  • 2
  • 11
  • 39
  • Saving the output in a local string would be faster than a getter or a object dereference. But this is measured in "teensy" – Jamie Apr 11 '16 at 18:46

5 Answers5

8

As Rogério answered, getting the object reference outside the loop (Object object = example.getValue();) will likely be faster (or will at least never be slower) than calling the getter inside the loop because

  • in the "worst" case, example.getValue() might actually do some very computationally-expensive stuff in the background despite that getter methods are supposed to be "trivial". By assigning a reference once and re-using it, you do this expensive computation only once.
  • in the "best" case, example.getValue() does something trivial such as return value; and so assigning it inside the loop would be no more expensive than outside the loop after the JIT compiler inlines the code.

However, more important is the difference in semantics between the two and its possible effects in a multi-threaded environment: If the state of the object example changes in a way which causes example.getValue() to return references to different objects, it is possible that, in each iteration, the method doSomething(Object object) will actually operate on a different instance of Object by directly calling doSomething(example.getValue());. On the other hand, by calling a getter outside the loop and setting a reference to the returned instance (Object object = example.getValue();), doSomething(object); will operate on object n times for n iterations.

This difference in semantics can cause behavior in a multi-threaded environment to be radically different from that in a single-threaded environment. Moreover, this need not be an actual "in-memory" multi-threading issue: If example.getValue() depends on e.g. database/HDD/network resources, it is possible that this data changes during execution of the loop, making it possible that a different object is returned even if the Java application itself is single-threaded. For this reason, it is best to consider what you actually want to accomplish with your loop and to then choose the option which best reflects the intended behavior.

Community
  • 1
  • 1
errantlinguist
  • 3,658
  • 4
  • 18
  • 41
5

It depends on the getter.

If it's a simple getter, the JIT will in-line it to a direct field access anyway, so there won't be a measurable difference. From a style point of view, use the getter - it's less code.

If the getter is accessing a volatile field, there's an extra memory access hit as the value can't be kept in the register, however the hit is very small.

If the getter is synchronized, then using a local variable will be measurably faster as locks don't need to be obtained and released every call, but the loop code will use the potentially stale value of the field at the time the getter was called.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • Thank you for your answer. The whole code is single threaded. So there are no volatile fields or synchronized methods. The getters are simple getters. – stonar96 Apr 11 '16 at 19:02
4

You should prefer a local variable outside the loop, for the following reasons:

  1. It tends to make the code easier to read/understand, by avoiding nested method calls like doSomething(example.getValue()) in a single line of code, and by allowing the code to give a better, more specific, name to the value returned by the getter method.
  2. Not all getter methods are trivial (ie, they sometimes do some potentially expensive work), but developers often don't notice it, assuming a given method is trivial and inexpensive when it really isn't. In such cases, the code may take a significant performance hit without the developer realizing it. Extraction into a local variable tends to avoid this issue.
Rogério
  • 16,171
  • 2
  • 50
  • 63
1

It's very easy to worry about performance much more than is necessary. I know the feeling. Some things to consider:

  1. 4096 is not much, so unless this has to complete in an extremely short time don't worry about performance so much.
  2. If there is anything else remotely expensive going on in this loop, the getter won't matter.
  3. Premature optimisation is the root of all evil. Focus on making your code correct and clear first. Then measure and profile it and narrow down the most expensive thing, and take care of that. Improve the actual algorithm if possible.

Regarding your question, I don't know exactly what the JIT does, but unless it can prove with certainty that example.getValue() or example.value doesn't change in the loop (which is hard to do unless the field is final and the getter is trivial) then there is logically no way it can avoid calling the getter repeatedly in the former sample since that would risk changing the behaviour of the program. The repeated calls are certainly some nonzero amount of extra work.

Having said all that, create the local variable outside the loop, whether or not it's faster, because it's clearer. Maybe that surprises you, but good code is not always the shortest. Expressing intent and other information is extremely important. In this case the local variable outside the loop makes it obvious to anyone reading the code that the argument to doSomething doesn't change (especially if you make it final) which is useful to know. Otherwise they might have to do some extra digging to make sure they know how the program behaves.

Alex Hall
  • 34,833
  • 5
  • 57
  • 89
  • "*then there is logically no way it can avoid calling the getter repeatedly*" => the getter method can still be inlined, regardless of what it is doing... – assylias Apr 11 '16 at 21:01
  • @assylias yes, but that is still some work, even if it's just checking the value of a field. – Alex Hall Apr 11 '16 at 21:03
0

If you need to run it as fast as possible, you should not use System.out.println in critical sections.

Concerning getter: There is slight overhead for using getter, but you should not bother about it. Java does have getter and setter optimization in JIT compiler. So eventually they will be replaced by native code.

Denis Kokorin
  • 887
  • 8
  • 17