I found this StackOverflow post:
Why does Python code run faster in a function?
The short answer for the post's question was "It is faster to store local variables than global ones". So, sometimes it is worth to put loops inside methods.
I have tried to check if this statement could be true for Java and wrote this sample:
public class Main {
// Global <<iter>> variable:
public static long ITER = (long) Math.pow(2, 35);
public static void main(String[] args) {
// call method from some loop:
long startTime1 = System.currentTimeMillis();
// meat 1:
for (long i = 0; i < Main.ITER; i++){
long p = Main.ITER;
}
// print results:
long stopTime1 = System.currentTimeMillis();
long elapsedTime1 = stopTime1 - startTime1;
System.out.println("Simple loop takes "
+ elapsedTime1 + " ms to finish.");
// put method in the loop:
long startTime2 = System.currentTimeMillis();
// meat 2:
myMethod1(Main.ITER);
// print results:
long stopTime2 = System.currentTimeMillis();
long elapsedTime2 = stopTime2 - startTime2;
System.out.println("Same loop in the method takes "
+ elapsedTime2 + " ms to finish.");
}
public static void myMethod1(long iter) {
for (long i = 0; i < iter; i++){
long p = iter;
}
}
}
I wanted the code to call Main.ITER
multiple times in meat 1
and only once in meat 2
part and then compare milliseconds spent for both. I ran it several times having always the results close to:
Simple loop takes 9199 ms to finish.
Same loop in the method takes 9123 ms to finish.
My JVM (Output from Eclipse installation details):
java.vm.info=mixed mode
java.vm.name=Java HotSpot(TM) 64-Bit Server VM
java.vm.specification.name=Java Virtual Machine Specification
java.vm.specification.vendor=Oracle Corporation
java.vm.specification.version=1.7
java.vm.vendor=Oracle Corporation
java.vm.version=24.80-b11
Here is bytecode for the loop from meat 1
part:
9 getstatic 20; /* test6.Main.ITER */
14 lload_3; /* i */
15 lconst_1;
16 ladd;
17 lstore_3; /* i */
18 lload_3; /* i */
19 getstatic 20; /* test6.Main.ITER */
22 lcmp;
23 iflt -14;
Here is bytecode for the loop in the method used in meat 2
part:
5 lload_0; /* iter */
6 lstore 4;
/* L32 */
8 lload_2; /* i */
9 lconst_1;
10 ladd;
11 lstore_2; /* i */
12 lload_2; /* i */
13 lload_0; /* iter <- No Main.ITER here ... */
14 lcmp;
15 iflt -10;
I am not an expert of Java bytecode, but it seems that myMethod1()
doesn't call global variable Main.ITER
.
Questions:
- Is it correct Java implementation for such a test? I might miss some general concepts about how JVM works and optimize this code.
- Do my results mean that there is no overhead of calling global variables in Java instead of local ones? E.g. it doesn't change the game if I put a loop in some method?
Thank you in advance.