Java local vs instance variable access speed
Ok, I've written a micro-benchmark (as suggested by @Joni & @MattBall) and here are the results for 1 x 1000000000 accesses for each a local and an instance variable:
Average time for instance variable access: 5.08E-4
Average time for local variable access: 4.96E-4
For 10 x 1000000000 accesses each:
Average time for instance variable access:4.723E-4
Average time for local variable access:4.631E-4
For 100 x 1000000000 accesses each:
Average time for instance variable access: 5.050300000000002E-4
Average time for local variable access: 5.002400000000001E-4
So it seems that local variable accesses are indeed faster that instance var accesses (even if both point to the same object).
Note: I didn't want to find this out, because of something I wanted to optimize, it was just pure interest.
P.S. Here is the code for the micro-benchmark:
public class AccessBenchmark {
private final long N = 1000000000;
private static final int M = 1;
private LocalClass instanceVar;
private class LocalClass {
public void someFunc() {}
}
public double testInstanceVar() {
// System.out.println("Running instance variable benchmark:");
instanceVar = new LocalClass();
long start = System.currentTimeMillis();
for (int i = 0; i < N; i++) {
instanceVar.someFunc();
}
long elapsed = System.currentTimeMillis() - start;
double avg = (elapsed * 1000.0) / N;
// System.out.println("elapsed time = " + elapsed + "ms");
// System.out.println(avg + " microseconds per execution");
return avg;
}
public double testLocalVar() {
// System.out.println("Running local variable benchmark:");
instanceVar = new LocalClass();
LocalClass localVar = instanceVar;
long start = System.currentTimeMillis();
for (int i = 0 ; i < N; i++) {
localVar.someFunc();
}
long elapsed = System.currentTimeMillis() - start;
double avg = (elapsed * 1000.0) / N;
// System.out.println("elapsed time = " + elapsed + "ms");
// System.out.println(avg + " microseconds per execution");
return avg;
}
public static void main(String[] args) {
AccessBenchmark bench;
double[] avgInstance = new double[M];
double[] avgLocal = new double[M];
for (int i = 0; i < M; i++) {
bench = new AccessBenchmark();
avgInstance[i] = bench.testInstanceVar();
avgLocal[i] = bench.testLocalVar();
System.gc();
}
double sumInstance = 0.0;
for (double d : avgInstance) sumInstance += d;
System.out.println("Average time for instance variable access: " + sumInstance / M);
double sumLocal = 0.0;
for (double d : avgLocal) sumLocal += d;
System.out.println("Average time for local variable access: " + sumLocal / M);
}
}
Java Optimization: Local Variable Vs Instance Variable
I wrote a little test program with jdk1.6, below
Results:
* 594ms for dostuff (which creates a local)
* 58ms for dostuff2 (which uses the instance)
public class Test {
static long counter=0;
public static void main(String[] args) {
long t1 = System.nanoTime();
Test test = new Test();
for (int i=0;i<1000000000;i++) {
test.doStuff();//or dostuff2
}
long t2 = System.nanoTime();
System.err.println((t2-t1)/1000000);
System.err.println(counter); // to check it wasnt optimised away
}
private void doStuff() {
List l = new ArrayList();
if (l!=null) {
counter++;
}
}
List l2 = new ArrayList();
private void doStuff2() {
if (l2!=null) {
counter++;
}
}
}
As a result, it seems that the instance is faster than using a local, as one would expect.
However it seems you save about 0.5s per billion items, on my PC at least, so you'd need to really really need the perf gain to justify it
Why static/member variable are slower than local variable?
youre a victim of runtime optimization :-)
if you change your code a little:
Question q = new Question();
for (int i=0; i<2; i++) {
q.executeGlobal();
q.executeStatic();
q.executeLocal();
}
you get this:
Type Global: 38331943 ns
Type Static: 57761889 ns
Type Local: 3010189 ns
Type Global: 46249688 ns
Type Static: 52745009 ns
Type Local: 0 ns
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
Is it faster to access final local variables than class variables in Java?
The final
keyword is a red herring here.
The performance difference comes because they are saying two different things.
public void forEach(IntIntProcedure p) {
final boolean[] used = this.used;
for (int i = 0; i < used.length; i++) {
...
}
}
is saying, "fetch a boolean array, and for each element of that array do something."
Without final boolean[] used
, the function is saying "while the index is less than the length of the current value of the used
field of the current object, fetch the current value of the used
field of the current object and do something with the element at index i
."
The JIT might have a much easier time proving loop bound invariants to eliminate excess bound checks and so on because it can much more easily determine what would cause the value of used
to change. Even ignoring multiple threads, if p.apply
could change the value of used
then the JIT can't eliminate bounds checks or do other useful optimizations.
Use local variable vs access instance variable
Do whatever is more readable.
Usually the shorter code is easier to read, comprehend, and show correct, but if an expression becomes long and the itermediate expressions make sense on their own, then introduce a local variable to make the code clearer.
As far as performance goes, you don't know that there will be any performance hit one way or the other unless you profile the code. Optimization in Java happens at compile but also at runtime with modern JIT compliation. Compilers can do inlining, common subexpression elimination and all kinds of algebraic transformations and strength reductions that I doubt that your example will show any performance impact one way or the other.
And unless an expression like this is executed a billion times or more in a loop, readability wins.
Why is local variable access faster than class member access in Python?
self.m += 1
means you have to look up a local variable called self
and then find the attribute called m
Of course if you just have to look up a local variable, it will be faster without the extra step.
It can be useful to look at what is happening under the hood:
>>> import dis
>>> dis.dis(StressTestLocal.do_work)
18 0 LOAD_CONST 1 (0)
3 STORE_FAST 1 (m)
19 6 LOAD_FAST 1 (m)
9 LOAD_CONST 2 (1)
12 INPLACE_ADD
13 STORE_FAST 1 (m)
20 16 LOAD_FAST 1 (m)
19 LOAD_CONST 3 (2)
22 INPLACE_MULTIPLY
23 STORE_FAST 1 (m)
26 LOAD_CONST 0 (None)
29 RETURN_VALUE
>>> dis.dis(StressTestMember.do_work)
10 0 LOAD_FAST 0 (self)
3 DUP_TOP
4 LOAD_ATTR 0 (m)
7 LOAD_CONST 1 (1)
10 INPLACE_ADD
11 ROT_TWO
12 STORE_ATTR 0 (m)
11 15 LOAD_FAST 0 (self)
18 DUP_TOP
19 LOAD_ATTR 0 (m)
22 LOAD_CONST 2 (2)
25 INPLACE_MULTIPLY
26 ROT_TWO
27 STORE_ATTR 0 (m)
30 LOAD_CONST 0 (None)
33 RETURN_VALUE
Related Topics
What Is the Purpose of the Java Constant Pool
How to Execute Windows Commands Using Java - Change Network Settings
Memory Leak When Redeploying Application in Tomcat
Visual Studio Code, Java Extension, How to Add a Jar to Classpath
Java 'Final' Method: What Does It Promise
Adding 3Rd Party Jars to Web-Inf/Lib Automatically Using Eclipse/Tomcat
How to Load/Reference a File as a File Instance from the Classpath
Should You Always Code to Interfaces in Java
Spring - Redirect After Post (Even with Validation Errors)
How to Create a Class Literal of a Known Type: Class<List<String>>
Split Regex to Extract Strings of Contiguous Characters
Accessing the Last Entry in a Map
Calling Win32 API Method from Java
Programmatically Shut Down Spring Boot Application
Java Convert Gmt/Utc to Local Time Doesn't Work as Expected