Java - Instruction set rather than time

One guy asked a question on a Java Forum: which operation is faster - post-increment or pre-increment. I really don't feel these things make a big difference in code performance. I have written a small code to check what nanosecond API of Java is telling about it. And again I reached to a wrong benchmarking. 

class InstructionCheck {
    private int x = 0;
 
    public void countup_() {
        ++x;
    }
    public void countup() {
        x++;
    }
    public void countdown() {
        x--;
    }
    public void count2up() {
        x = x+2;
    }
    public void count2down() {
        x = x-2;
    }
    public static void main(String[] args) {
        long stime = 0;
        long etime = 0;
        InstructionCheck ic = new InstructionCheck();

        stime = System.nanoTime();
        ic.countup_();
        System.out.println(System.nanoTime() - stime);

        stime = System.nanoTime();
        ic.countup();
        System.out.println(System.nanoTime() - stime);

        stime = System.nanoTime();
        ic.countdown();
        System.out.println(System.nanoTime() - stime);

        stime = System.nanoTime();
        ic.count2up();
        System.out.println(System.nanoTime() - stime);

        stime = System.nanoTime();
        ic.count2down();        
        System.out.println(System.nanoTime() - stime);
    }
}         

And the output after several run: 

20952
5308
5587
5587
5308

Now, no doubt the first value is not correct, because of some other reason(I really don't know why) but may be some reigster setting, first time using the class or something else.

But if we see the assemble code, it will simple say that there is(should) no difference in ++i or i++. Look at this :

public void countup_();
  Code:
   0:   aload_0
   1:   dup
   2:   getfield        #2; //Field x:I
   5:   iconst_1
   6:   iadd
   7:   putfield        #2; //Field x:I
   10:  return

public void countup();
  Code:
   0:   aload_0
   1:   dup
   2:   getfield        #2; //Field x:I
   5:   iconst_1
   6:   iadd
   7:   putfield        #2; //Field x:I
   10:  return

The complete assemble code, you can see by option javap -c FileName. My personal opinion is to check the instruction set rather checking the time by nanosecond or millisecond because some benchmarking issue can lead to a different result(which can be completely wrong, like in our case). Here we can easily see that ++i and i++ leads to same instruction and hence both will be more or less equal in performace.

Comments:

My guess is the first call reflects the time it takes to JIT the InstructionCheck class. You should call all your methods once first, then do the timings.

Posted by Alan Burlison on September 21, 2008 at 08:06 PM IST #

I have changed my main like this :

public static void main(String[] args) {
long stime = 0;
long etime = 0;
InstructionCheck ic = new InstructionCheck();

ic.countup_();
ic.countup();
ic.countdown();
ic.count2up();
ic.count2down();

stime = System.nanoTime();
ic.countup_();
System.out.println(System.nanoTime() - stime);

stime = System.nanoTime();
ic.countup();
System.out.println(System.nanoTime() - stime);

stime = System.nanoTime();
ic.countdown();
System.out.println(System.nanoTime() - stime);

stime = System.nanoTime();
ic.count2up();
System.out.println(System.nanoTime() - stime);

stime = System.nanoTime();
ic.count2down();
System.out.println(System.nanoTime() - stime);
}

And the output :
12120
1441
1393
1333
1299
(this machine is faster than prev. one) but the first value is still high).

Posted by Vaibhav Choudhary on September 22, 2008 at 03:19 AM IST #

This happens because of PrintStream. So, we can change the code to :

public static void main(String[] args) {
InstructionCheck ic = new InstructionCheck();
long stime = 0;
long etime = 0;

System.out.println("Hello World");

stime = System.nanoTime();
ic.countup();
........
........
........

Posted by Vaibhav Choudhary on September 22, 2008 at 04:36 AM IST #

Why do you think that the bytecode instructions should tell you something about execution performance? (If so )
If you really want to know what's executed you should check the hotspot assembler code output.
BTW: Microbenchmarks on a cold VM will never prove anything useful.

Posted by Stefan on September 22, 2008 at 10:19 AM IST #

what if the same instruction is getting executed. It will def.'ly give a hint that time going to take by two operator or method are same. Like it happens in ++i and i++. Yes, that's right, on Cold VM nothing is useful. I don't know how to make it hot, probably learning with mistakes.

Posted by Vaibhav on September 22, 2008 at 06:01 PM IST #

Take a look at this code, and use the following VM options. Then you will see that there is no difference.

public class Test {

private int x = 0;

long countup_ = Long.MAX_VALUE;

public void countup_() {
x++;
}

long _countup = Long.MAX_VALUE;

public void _countup() {
++x;
}

long countdown_ = Long.MAX_VALUE;

public void countdown_() {
x--;
}

long _countdown = Long.MAX_VALUE;

public void _countdown() {
x--;
}

long count2up = Long.MAX_VALUE;

public void count2up() {
x = x + 2;
}

long count2down = Long.MAX_VALUE;

public void count2down() {
x = x - 2;
}

public static void main(String[] args) {
new Test().doCount();
}

public void doCount() {
for (int i = 0; i < 400000; i++) {
long stime;
long etime = Long.MAX_VALUE;

countup_();
_countup();
countdown_();
count2up();
count2down();

stime = System.nanoTime();
countup_();
etime = System.nanoTime() - stime;
countup_ = countup_ > etime ? etime : countup_;

stime = System.nanoTime();
_countup();
etime = System.nanoTime() - stime;
_countup = _countup > etime ? etime : _countup;

stime = System.nanoTime();
countdown_();
etime = System.nanoTime() - stime;
countdown_ = countdown_ > etime ? etime : countdown_;

stime = System.nanoTime();
_countdown();
etime = System.nanoTime() - stime;
_countdown = _countdown > etime ? etime : _countdown;

stime = System.nanoTime();
count2up();
etime = System.nanoTime() - stime;
count2up = count2up > etime ? etime : count2up;

stime = System.nanoTime();
count2down();
etime = System.nanoTime() - stime;
count2down = count2down > etime ? etime : count2down;
}

System.out.println("countup++: " + countup_);
System.out.println("++countup: " + _countup);
System.out.println("countdown--: " + countdown_);
System.out.println("--countdown: " + _countdown);
System.out.println("count2up: " + count2up);
System.out.println("count2down: " + count2down);

System.out.println(x);
}

}

## VM Options (java.version=1.6.0_10-beta)
-client -Xdebug -XX:CompileThreshold=50 -XX:+AggressiveOpts -XX:MaxPermSize=10m -XX:+UseFastAccessorMethods -XX:-CITime -XX:-PrintCompilation -Xprof -XX:+UseBiasedLocking

Regards,
Bruno

Posted by Bruno Borges on September 22, 2008 at 10:24 PM IST #

For more information about VM Options, look at

http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp

m2c :-)

Posted by Bruno Borges on September 22, 2008 at 10:26 PM IST #

thats nicely written Bruno :). thanks !

Posted by Vaibhav Choudhary on September 23, 2008 at 06:19 AM IST #

Post a Comment:
Comments are closed for this entry.
About

Hi, I am Vaibhav Choudhary working in Sun. This blog is all about simple concept of Java and JavaFX.

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today