I've seen this thread: Speed of if compared to conditional
Made my own class for checking the speed
public class Question {
static long startTime;
static long elapsedTime;
static String mStatic;
private String mPublic;
public static void main(String[] args) {
Question q = new Question();
q.executeGlobal();
q.executeStatic();
q.executeLocal();
}
public void executeLocal() {
String mLocal;
startTime = System.nanoTime();
for (int i = 0; i < 1000000000; i++) {
mLocal = "";
}
elapsedTime = System.nanoTime() - startTime;
System.out.println("Type Local: " + elapsedTime + " ns");
}
public void executeGlobal() {
startTime = System.nanoTime();
for (int i = 0; i < 1000000000; i++) {
mPublic = "";
}
elapsedTime = System.nanoTime() - startTime;
System.out.println("Type Global: " + elapsedTime + " ns");
}
public void executeStatic() {
startTime = System.nanoTime();
for (int i = 0; i < 1000000000; i++) {
mStatic = "";
}
elapsedTime = System.nanoTime() - startTime;
System.out.println("Type Static: " + elapsedTime + " ns");
}
}
Result:
Type Global: 45693028 ns
Type Static: 43853723 ns
Type Local: 2057505 ns
In the answer @Rod_algonquin answered that it is because of the getstatic/putstatic bytecode for static variable and getfield/putfield bytecode for the member variable, that it is calculating through bit-shifting and some addition.
At first I thought that only Objects causes this, but upon trying to reference primitive the result is the same local variable
is still faster.
Why is that local variable is faster? except the bytecode explanation.
youre a victim of runtime optimization :-)
if you change your code a little:
you get this:
what happens is that pretty soon the runtime realizes that your local variable keeps getting assigned, but never gets read (or used), and optimizes out the whole loop.
as for the difference between class instance fields and static fields, theyre both on the heap, but the static fields are shared across all object instances, so there's an extra level of indirection
In general, jvm uses three different memory segments
Stack values only exist within the scope of the function they are created in. Once it returns, they are discarded.
Heap values however exist on the heap. They are created at some point in time, and destructed at another (either by GC or manually). Java only stores primitives on the stack. This keeps the stack small and helps keeping individual stack frames small, thus allowing more nested calls. Objects are created on the heap, and only references (which in turn are primitives) are passed around on the stack.
Java uses three different kind of variables
Accessing the Stack is relatively faster (though, it is purely JVM implementation specific) than Code segment and hence theistically accessing local variable is faster than global.
For details, you can check http://blog.jamesdbloom.com/JVMInternals.html or it-haggar_bytecode
There is another article that analyze the performance of static vs local variable
Another reason could be the cache missing.
Cache misses bring a ~250% penalty , when CPU needs to refresh it's cache (that means the variable you are trying to access isn't in the CPU cache is in RAM).
Looking at the results of your test, it seems to be a cache miss problem :
Your local variables (mLocal and i ) are accessed in every cycle, but they are close to one another in memory since they were added to the stack recently.
mPublic and mStatic aren't within the same page of memory as "i". So your for loop should switch memory pages between the page where "i" with the page where mPublic / mStatic is .
Ofc you cannot know how memory actually gets mapped, so this is just a guess.
If you are at it, could you do another experiment ? Declare a static integer next to the static mStatic variable and use that integer in the loop. Is performance improving ?