41

In java I usually make a for-loop like following:

for (int i = 0; i < max; i++) {
   something
}

But recently a colleague typed it so:

for (int i = 0; i < max; ++i) {
   something
}

He said the latter would be faster. Is that true?

IAdapter
  • 62,595
  • 73
  • 179
  • 242
Binabik
  • 437
  • 1
  • 4
  • 6
  • 7
    I think you will have trouble to measure the evantual difference. Better results are generally achieved by optimizing the part *inside* the loop ;) – Felice Pollano Jan 28 '11 at 18:30
  • 2
    It might be, but so little that you'd never even notice. Micro-optimizations like this are totally useless. – Rafe Kettler Jan 28 '11 at 18:31
  • 1
    @PeeHaa: Both loops run same amount of cycles. I tried with max =10 and they both go from 0 to 9 for i. – Mnementh Jan 28 '11 at 18:36
  • @Linus Kleen There's nothing odd about these questions getting lots of views - Programmers tend to love tricks and tweaks, and the idea that they are writing powerful and fast code... Most programmers learn to code, and then have to learn not to over-optimize their code. – jball Jan 28 '11 at 18:47
  • see also: http://stackoverflow.com/questions/1918196/why-doesnt-changing-the-pre-to-the-post-increment-at-the-iteration-part-of-a-for – user85421 Jan 28 '11 at 20:04

11 Answers11

63

No, it's not true. You could measure the performance by timing each loop for a large number of iterations, but I'm fairly certain they will be the same.

The myth came from C where ++i was regarded as faster than i++ because the former can be implemented by incremeting i then returning it. The latter might be implemented by copying the value of i to a temporary variable, incrementing i, then returning the temporary. The first version doesn't need to make the temporary copy and so many people assume that it is faster. However if the expression is used as a statement modern C compilers can optimize the temporary copy away so that there will be no difference in practice.

Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • 12
    Modern compilers will indeed optimize this, but if you are using C++, and i is an object (say, an interator), and those operators are not inline, ++i will be faster than i++. – fbafelipe Jan 28 '11 at 18:58
  • Also, if you go to a job interview you should say it is faster :) But if you start using iterators in c++, there is no such thing as it++. And you'll keep banging your head against the wall for receiving the same stupid error msg's over and over again. Like me x) – Barney Szabolcs Oct 30 '12 at 11:51
  • 1
    @BarnabasSzabolcs post-increment is definable for iterators, you just haven't been using the right ones (or the wrong ones, depending on your view). – JAB Apr 03 '14 at 12:24
46

This question needed some Java byte code. Consider the following code:

public class PostPre {
    public static void main(String args[]) {
        int n = 5;
        loop1(n);
        loop2(n);
    }

    public static void loop1(int n) {
        for (int i = 0; i < n; i++) {}
    }

    public static void loop2(int n) {
        for (int i = 0; i < n; ++i) {}
    }
}

Now compile it and disassemble it:

$ javac PostPre.java; javap -c PostPre.class 
Compiled from "PostPre.java"
public class PostPre {
  public PostPre();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return        

  public static void main(java.lang.String[]);
    Code:
       0: iconst_5      
       1: istore_1      
       2: iload_1       
       3: invokestatic  #2                  // Method loop1:(I)V
       6: iload_1       
       7: invokestatic  #3                  // Method loop2:(I)V
      10: return        

  public static void loop1(int);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iload_1       
       3: iload_0       
       4: if_icmpge     13
       7: iinc          1, 1
      10: goto          2
      13: return        

  public static void loop2(int);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iload_1       
       3: iload_0       
       4: if_icmpge     13
       7: iinc          1, 1
      10: goto          2
      13: return        
}

loop1() and loop2() have the same byte code.

gsgx
  • 12,020
  • 25
  • 98
  • 149
9

For any reasonably capable optimizer, they will be exactly the same. If you aren't sure, look at the output bytecode or profile it.

Rafe Kettler
  • 75,757
  • 21
  • 156
  • 151
Carl Norum
  • 219,201
  • 40
  • 422
  • 469
6

Even if it is, which I very much doubt, your colleague should really have better things to spend his time learning than how to optimise a loop expression.

biziclop
  • 48,926
  • 12
  • 77
  • 104
  • 16
    Look, ma! My program runs faster if I only use letters from the first half of the alphabet for variable names! To the refactoring machine! – Rafe Kettler Jan 28 '11 at 18:32
  • 1
    @Rafe Kettler Would be scary if it was true though. :) – biziclop Jan 28 '11 at 18:34
  • 3
    the scary thing is that in many compilers, shorter variable names use less memory. We could obsess all day long about tiny hacks, but my processor doesn't have 730 million transistors on it for no reason. – Rafe Kettler Jan 28 '11 at 18:38
  • 1
    @Rafe Kettler It wouldn't be the craziest theory I've heard, that award has to go to the idea that a hard drive weighs more if it has more information on it. – biziclop Jan 28 '11 at 18:41
  • @biziclop Maybe if you put a newspaper on it – mike Aug 23 '13 at 12:21
2

Try this in your environment

public class IsOptmized {
    public static void main(String[] args) {

        long foo; //make sure the value of i is used inside the loop
        long now = 0; 
        long prefix = 0;
        long postfix = 0;

        for (;;) {
            foo = 0;
            now = System.currentTimeMillis();
            for (int i = 0; i < 1000000000; i++) {
                foo += i;
            }
            postfix = System.currentTimeMillis() - now;

            foo = 0;
            now = System.currentTimeMillis();
            for (int i = 0; i < 1000000000; ++i) {
                foo += i;
            }
            prefix = System.currentTimeMillis() - now;

            System.out.println("i++ " + postfix + " ++i " + prefix + " foo " + foo);
        }
    }
}

Mine gives me

i++ 1690 ++i 1610 foo 499999999500000000
i++ 1701 ++i 1610 foo 499999999500000000
i++ 1701 ++i 1600 foo 499999999500000000
i++ 1701 ++i 1610 foo 499999999500000000
i++ 1701 ++i 1611 foo 499999999500000000
i++ 1701 ++i 1610 foo 499999999500000000
i++ 1691 ++i 1610 foo 499999999500000000
i++ 1701 ++i 1600 foo 499999999500000000
i++ 1701 ++i 1610 foo 499999999500000000
i++ 1691 ++i 1610 foo 499999999500000000
i++ 1701 ++i 1610 foo 499999999500000000
i++ 1691 ++i 1610 foo 499999999500000000
i++ 1701 ++i 1610 foo 499999999500000000
i++ 1701 ++i 1610 foo 499999999500000000
i++ 1701 ++i 1610 foo 499999999500000000
i++ 1692 ++i 1610 foo 499999999500000000
i++ 1701 ++i 1610 foo 499999999500000000
i++ 1691 ++i 1610 foo 499999999500000000

So even if it is not that much, I asume there is a difference

Disc-Addict
  • 138
  • 12
1

Decompile with "javap -c YourClassName" and see the result and decide from that. This way you see what the compiler actually does at each case, not what you think it does. This way you also see WHY one way is faster than the other.

Aulo Aasmaa
  • 11
  • 1
  • 3
1

In Java there is no such difference. Java machine interpertes code and no matter if you write ++i or i++, it will be converted to byte code to exact same instruction set.

But in C/C++ there is a huge difference and if you are not using any optimisation flags, then your loop can be slower up to 3 times.

Using optimisation flags such like -O/-O3 will force compiler to make output asembly code simplier (in most cases) and therefore faster (in most cases).

1

It will not be any faster. The compiler and JVM with the JIT will make mincemeat of such insignificant differences.

You can use the usual loop optimization techniques to get speed benefits, like unrolling, if applicable.

martona
  • 5,760
  • 1
  • 17
  • 20
1

No there will be no difference at all.

This came from C++ but even there there would be no difference at all in this case. Where there is a difference is where i is an object. i++ would have to make an additional copy of the object as it has to return the original unchanged value of the item whereas ++i can return the changed object so saves a copy.

In c++ with user defined object the cost of a copy can be significant so it's definatly worth remembering. And because of this people tend to use it for int variables too, as it's just as good anyway...

jcoder
  • 29,554
  • 19
  • 87
  • 130
0

In Java there should be no difference - any modern compiler* should generate the same byte code (just an iinc) in both cases since the result of the increment expression is not being used directly.
There is a third option, still the same byte code*:

for (int i = 0; i < max; i += 1) {
   something
}

* tested with Eclipse's compiler

user85421
  • 28,957
  • 10
  • 64
  • 87
-2

Even it one would be faster, nobody cares in the days of HotSpot. The first thing the JIT does is to remove all optimizations that javac made. After that, everything is left to the JIT to make it fast.

Ivo Wetzel
  • 46,459
  • 16
  • 98
  • 112