Crazy result of Java performance test

Accname

2D-Graphics enthusiast
Reaction score
1,462
Hi guys, just wanted to share this with you.
Lets say I have a class like this:
Code:
public class CrazyClass {
        public int x;
        public int getX() {
                return x;
        }
}
I was curious which was faster:
Code:
new CrazyClass().x;
or
Code:
new CrazyClass().getX();

So I made a simple test:
Code:
        int runCount = 1000000;
        int sum = 0;
        CrazyClass c = new CrazyClass();
        long timestamp = System.nanoTime();
        for (int i = 0; i < runCount; i++) {
            sum += c.x;
        }
        System.out.println("Time since: "+(System.nanoTime() - timestamp)+" Nanoseconds.");
       
        sum = 0;
        timestamp = System.nanoTime();
        for (int i = 0; i < runCount; i++) {
            sum += c.getX();
        }
        System.out.println("Time since: "+(System.nanoTime() - timestamp)+" Nanoseconds.");
}
And I let the above code run 100 times.
The result was baffling, the get-method was actually faster then accessing the value directly.
I always thought it would be the other way around.

Well, it probably is the other way around for languages like C++ and alike, but apparently its faster in Java to call a method.

Just loling. I wanted to share this with you guys.
 

s3rius

Linux is only free if your time is worthless.
Reaction score
130
Now, here comes the funny part:

Try to switch the order of tests around. Let it first do the c.getX() and then c.x.
You'll see that, suddenly, c.x is now faster =).

Or, to be more exact: The first test is always slower than the second test.
That's Java's Just In Time optimizer working.

After a couple of thousand iterations it can recognize that c is a "hot spot" and it'll optimize in order to allow you better access times. So the second test can make full use of that.

I've modified the test to do 10000000000 iterations instead of 1000000.
This way the delay that JIT needs to kick in is irrelevant in comparison to the time it takes to complete even the first loop.

Code:
1. Test
Time since: 7148381343 Nanoseconds. ( c.getX() )
Time since: 7145716720 Nanoseconds. ( c.x )
 
2.Test
Time since: 7140480574 Nanoseconds. ( c.x )
Time since: 7140505095 Nanoseconds. ( c.getX() )

As you can see there is no real difference between the two. The method call gets optimized away.

Other languages such as C++ will generally do that same. They don't have a JIT (usually) but during compilation, useless function calls like c.getX() will be removed and replaced with c.x.
 

Accname

2D-Graphics enthusiast
Reaction score
1,462
Hm, good point. I really thought a million was a good sample size to already eliminate these kinds of optimization effects. I was proven wrong.
 

s3rius

Linux is only free if your time is worthless.
Reaction score
130
Yea, it's counter-intuitive, but a million iterations on a loop that doesn't do much is basically nothing for the CPU.
As a rule of thumb I'd say no performance test should run for less than a few seconds, and you should always run the test several times without restarting the program (since Java needs a while to warm up).
 

camelCase

The Case of the Mysterious Camel.
Reaction score
362
Fun fact, in Android, getters and setters suck.
I guess it's the dalvik machine?

http://developer.android.com/training/articles/perf-tips.html
Avoid Internal Getters/Setters


In native languages like C++ it's common practice to use getters (i = getCount()) instead of accessing the field directly (i = mCount). This is an excellent habit for C++ and is often practiced in other object oriented languages like C# and Java, because the compiler can usually inline the access, and if you need to restrict or debug field access you can add the code at any time.
However, this is a bad idea on Android. Virtual method calls are expensive, much more so than instance field lookups. It's reasonable to follow common object-oriented programming practices and have getters and setters in the public interface, but within a class you should always access fields directly.
Without a JIT, direct field access is about 3x faster than invoking a trivial getter. With the JIT (where direct field access is as cheap as accessing a local), direct field access is about 7x faster than invoking a trivial getter.
Note that if you're using ProGuard, you can have the best of both worlds because ProGuard can inline accessors for you.
 
General chit-chat
Help Users

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top