While he agreed to change the style of his code, he was still reluctant to move the declaration of a variable used only within a loop from outside it to inside it. For example, he was reluctant to change:
String s;
for( int i = 0; i < 10; i++)
{
s = String.valueOf( i);
}
to:
for( int i = 0; i < 10; i++)
{
String s = String.valueOf( i);
}
He believed that only one variable is created in the former case while 10 variables are created in the latter - clearly it is more efficient to declare a single variable outside the loop and keep reusing it inside the loop!
I then pointed out the section in the JVM specification that says that a JVM uses a fixed-size array for storing the values of local variables used in a method and each local variable maps to an index in this array. A Java compiler calculates the size of this array during the compilation of a method and declares it in the generated bytecode for the method.
Since he was still sceptical, I compiled both the variants to bytecode, used
javap -c
to produce the dissassembled code and used diff
to show that the generated code was the same in both the cases (except for the indices used for s
and i
). I then used a simple modification of using the JVM Emulator Applet written by Bill Venners as a standalone application to show the bytecode variants in execution and demonstrate that the size of the local variables array really remains constant throughout.He was finally convinced.
On the other extreme, I have another colleague who is in the masochistic habit of introducing new scopes to isolate the local variables used only in a section of a method's body. That is, something like:
{
Foo x = wombat.snafu( );
// Use x here.
...
}
{
Bar y = new Bar( a, b, c);
// Use y here.
...
}
|
Tweet |
|
Ah! I am under the same habit too of declaring variables outside loops. Good info!
ReplyDeleteChris: I forgot to mention that the second colleague I talked about in the post is also in the habit of declaring everything "final" as much as possible, somewhat similar to what you note.
ReplyDeleteI should have mentioned that the source code to Bill Venners's Java emulator applet can be found in http://www.artima.com/insidejvm/applets/sourcecode.html. It is not very good at disassembling bytecode and it has problems in stepping over instructions that invoke methods, but it is quite an instructive tool otherwise.
I guess you are kawigi :)
ReplyDeleteAnyways, I wanted to know if this is also true for c++. I also think that method 2 is more readable.. I want to use it... but the performance issue in method 2 forces me to use method 1.
Ohh! you are not Mathew Reeder. Anyways I would appreciate if you could answer my question.
ReplyDeleteTurbo: I believe that even in C/C++ there is no difference in performance between the two. Each local variable is assigned a stack slot and the compiler is usually able to recognise the lifetime of such variables to be able to reuse such stack slots. To be perfectly sure, you can see the assembly created in each case (e.g. "gcc -S foo.cpp") to verify this assertion.
ReplyDelete