• Post Reply Bookmark Topic Watch Topic
  • New Topic

Declaration-difference in/outside a loop  RSS feed

 
Sebastian Krzyzanowski
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Asume the following situation
(2 pieces of code):

java.util.Vector v= someobj.getVectorFromSomewhere();
for(int i=0;i < v.size();i++)
{
String element=(String)v.elementAt(i);
...
}

OR

java.util.Vector v= someobj.getVectorFromSomewhere();
String element=null;
for(int i=0;i < v.size();i++)
{
element=(String)v.elementAt(i);
...
}
Once the declaration of 'element' is made inside (hence: each time), once outside the loop. The question is:
What is the "internal" difference between these two possibilities?

* Is one way faster than the other? Which one?
* Which method consumes more memory - if at all?
* Forgetting garbage collection for a moment: are "memory leaks" / "dangling pointers" more / less possible in one method? In which one?
 
Wendal Park
Ranch Hand
Posts: 39
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Use the second method, for sure!
Then for each element in the Vector, you just use the same reference assigning to it, thus saving memory usage.
Also, there won't be something like "dangling pointers" in Java ... the closest relative would be the NullPointerException (a Runtime Exception). This is something due to accessing an index outside the size of an Array or String in most cases. So it is kind of irrelevant in this case.
Since you probably won't need the previous String object retrieved from the Vector after each loop, why do you need new reference to it? And this may trigger GC for large Vector size ... Therefore usign one String reference (like in 2nd case) can surf the purpose, although both ways should work fine afterall.
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here is a small benchmark I wrote:

On my system (Windows, JDK 1.4.1), this shows about a 20 percent difference (to my surprise) in favor of declaring the variable outside the loop. This may differ on your system, of course.
I don't think there should be any differences in memory consumption - as far as I know, a local variable inside the loop will be reused, two.
There are other implications, though. If a variable only gets used inside a loop, it communicates much better if it also gets declared there. It also simplifies refactorings like extract method.
Remember - generally maintenance is much more important than performance!
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ilja - using your program on my system (JDK 1.4.1 on Win XP) I observed that declaring outside the loop was more like twice as fast as declaring inside the loop ( !) Then I tried reversing the order of the tests, and found the opposite result. I think you're just observing JIT effects. What's particularly odd is that your outer "count" loop manages to reset this effect, so that the third test run takes twice as long again, like the first, and the fourth is comparable to the second. Very strange. That damn HotSpot sure makes accurate performance testing difficult. Running the tests in separate JVM instances, both inner and outer declarations seem to give the same results (subject to random variations in each execution).
[ January 24, 2003: Message edited by: Jim Yingst ]
 
Peter den Haan
author
Ranch Hand
Posts: 3252
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Vector... Yech. Who still uses Vector.
There is zero, zip, zilch performance difference. Upon entry into a method, a stack frame is allocated that is large enough for ALL variables declared in any scope within the method.
Compile both your code samples and use javap -c to decompile the class files. The compiler generates completely identical code for both. It doesn't get more conclusive than that
- Peter
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Peter den Haan:
There is zero, zip, zilch performance difference. Upon entry into a method, a stack frame is allocated that is large enough for ALL variables declared in any scope within the method.
Compile both your code samples and use javap -c to decompile the class files. The compiler generates completely identical code for both. It doesn't get more conclusive than that

Hell, I would have bet that it is that way - that is why I was surprised by the benchmark... :roll:
Fascinating - I changed the benchmark a little bit, and now it shows absolutely the same performance for both loops:

Seems as if Hotspot had some problems with the first loop in the former benchmark?!?
 
Anonymous
Ranch Hand
Posts: 18944
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Peter den Haan:
There is zero, zip, zilch performance difference. Upon entry into a method, a stack frame is allocated that is large enough for ALL variables declared in any scope within the method.

You're absolutely right of course. Every self respecting compiler is able to calculate the union of all stackframe snapshots an figure the maximum total size of that frame including the ofsets of the local variables stored therein.
James Gosling et. al. were clever enough to demand that local variables must be initialized either in their declaration statement or before their first usage as an rvalue, so no additional 'setup stuff' is needed when a variable is being declared.
kind regards
 
Sebastian Krzyzanowski
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks a lot for all suggestions hints and benchmarks.
Mainly I was afraid that declaring a bunch of variables inside a loop which is traversed some thousend times could result in serious memory (and further performance) loss, since new memory is allocated (each time) - possibly before the old one can be freed by garbage collection...
Even with allocating a large enough stackframe first, I would assume that the allocated size differs largely for the both possibilities...
Or are local variables declared inside a loop (and hence the memory of these variables) really reused?
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Sebastian Krzyzanowski:

Or are local variables declared inside a loop (and hence the memory of these variables) really reused?

Yes - and they are not garbage collected, because they aren't stored on the heap, but on the stack. The memory is allocated at method entry and deallocated at method exit.
 
Peter den Haan
author
Ranch Hand
Posts: 3252
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Sebastian Krzyzanowski:
Even with allocating a large enough stackframe first, I would assume that the allocated size differs largely for the both possibilities...
As I said the generated code is identical for both. Blimey, just use javap -c, it's part of your JDK, just see for yourself...
- Peter
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!