• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

For Loop Test Condition Performance Question

 
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Lets say I have a simple String array called 'rules'.

In the for loop below, is the 'length' value of this array being retrieved every time through the loop?
for (int i = 1; i < rules.length; i++)

Would this perform better by doing the following (or is the result the same)?
int rulesLength = rules.length;
for (int i = 1; i < rulesLength; i++)

Thanks for your input!
Dave
 
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes there can be a difference. The spec allows the compiler to automatically optimize this but doesn't require it to. Running a test using Sun 1.5, iterating over 1000000 strings, results in the following:

for (int i = 0; i < rules.length; i++) 1861516 nanos

int len = rules.length;
for (int i = 0; i < len; i++) 1619266 nanos

About a 10% difference, which depending on what you're doing, may or may not be significant.

It's more important to do this kind of optimization when method calls are involved, like with a Collection. Doing the same test but putting the 1000000 strings into an ArrayList and using size(), results in:

for (int i = 0; i < list.size(); i++) 9949896 nanos

int len = list.size();
for (int i = 0; i < len; i++) 1615477 nanos

Over an 80% difference.
 
Ranch Hand
Posts: 1970
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The Java compiler (javac) typically will not optimise this loop invariant, but I would expect HotSpot (the bytecode to native just-in-time compiler) to do so. So I am surprised that you find such a significant measured difference in timings.

It is very difficult to make accurate comparisons of performance in Java programs, so knowing exactly what you did would be interesting.

In general, one should not bother with micro-optimisations of this type in code. It is hugely more important to make your code as concise, and yet readable, as possible. Only when you have found that your program is too slow, and you have profiled it to prove that this loop is critical, should you start micro-optimising.
 
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
[Peter]: The Java compiler (javac) typically will not optimise this loop invariant, but I would expect HotSpot (the bytecode to native just-in-time compiler) to do so. So I am surprised that you find such a significant measured difference in timings.

The original 10% difference is pretty much insignificant, considering the tests ran less than two seconds each. It's not unusual for the results of such tests to vary 20% or more each time you run them. The later test using size() and showing an 80% difference, that's much more significant - but I wouldn't expect hotspot to necessarily optimize it away, since it's much less obvious that size() is invariant. With an array length, Hotspot knows right away that it's final - assuming the array reference itself doesn't change, and Hotspot can see that's held by a local variable which is never assigned to, so it doesn't. But with an ArrayList's size(), there are a whole buch of public methods that could change that, and Hotspot would need to check whether any other threads have a reference to the ArrayList and whether they call those methods. I don't know if Hotspot does that sort of thing or not, but it seems a bit more complicated than the first case.

I ran a set of tests of my own over a much longer time period, and came up with approximately equal results for both

and

I also tried changing "int len" to "final int len" and got the same result - Hotspot seems to be able to figure out it's invariant without declaring the variable final, in this case. I also tried an enhanced for loop, and it was 10% faster than the other three. Apparently the compiler and/or Hotspot are able to optimize this case better than the others, which is nice. 10% is still fairly unimportant in the grand scheme of things (especially if you actually do anything inside the loop, which will increase the overall time and decrease the importance of the loop optimization) but it's something.
 
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Programmers are always determined to pre-optimize in situations that don't benefit from it, but in my opinion assinging the size of your list to a variable doesn't fall into that category. Here's why:

It's not complex
It's not tricky
It's easy to understand
It's obvious why you did it

Lots of "optimizations" have pro's, and con's - I have a hard time finding any real "con's", especially if you mark it final.

Often times you may need access to this size attribute while in the loop body, and then it's quite obvious that it should be externalized. If the collection size is fairly small - say under 1000, and the size is not needed within the loop body, it may not be important to fetch and assign, but it doesn't really hurt.
 
Ranch Hand
Posts: 209
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Use the following construct, not too complicated, and you get all the optimization. "n" is scoped in the for block, so it disappears with i.

 
reply
    Bookmark Topic Watch Topic
  • New Topic