Java local vs instance variable access speed

Solution 1:

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);
    }
}

Solution 2:

In general, an access to an instance variable (of the this object) requires an aload_0 (to load this to the top of the stack) followed by getfield. Referencing a local variable requires only the aload_n to pull the value out of its assigned location in the stack.

Further, getfield must reference the class definition to determine where in the class (what offset) the value is stored. This could be several additional hardware instructions.

Even with a JITC it's unlikely that the local reference (which would normally be zero/one hardware operation) would ever be slower than the instance field reference (which would have to be at least one operation, maybe 2-3).

(Not that this matters all that much -- the speed of both is quite good, and the difference could only become significant in very bizarre circumstances.)