6
public class Test {

    public static void main(String[] args) {

        int x = 150_000;

        long start = System.currentTimeMillis();
        for(int i = 0; i < x; i++) {            
            f1(i);
        }
        long end = System.currentTimeMillis();
        System.out.println((end - start) / 1000.0);
    }

    private static long f1(int n) {
        long x = 1;
        for(int i = 0; i < n; i++) {
            x = x + x;
        }
        return x;
    }
}

Can someone explain why setting x to 150_000 or 4_000_000 or even 2_000_000_000 doesn't change execution time of this loop?

TylerH
  • 20,799
  • 66
  • 75
  • 101
  • 18
    Probably the compiler is smart enough to detect that nothing is happening in the loop so it optimizes out. – Tunaki Oct 12 '15 at 14:01
  • @Tunaki That would be my guess as well. `f1` is returning some value, but that value is never used, and no other variables are being modified during the method. It would sense (to me at least) that the compiler completely ignores the call. – Mage Xy Oct 12 '15 at 14:03
  • Your compiler optimised this for you. It probably ignores a f1(i) call. If you wish to see the difference, try to define a long type variable, initialize it every time as l = f1(i); and then print it out after exiting the loop. You'll see the difference – Stanislav Oct 12 '15 at 14:06
  • i dont code java, but isnt 150_000, 4_000_000 and 2_000_000_000 interpreted as 150, 4, 2? – Pepo_rasta Oct 12 '15 at 14:06
  • 2
    @Pepo_rasta No. Underscores are now allowed in int and long literals (from Java 1.7 I think). – Paul Boddington Oct 12 '15 at 14:07
  • 4
    Possible duplicate of [Java: how much time does an empty loop use?](http://stackoverflow.com/questions/7271147/java-how-much-time-does-an-empty-loop-use) – Murat Karagöz Oct 12 '15 at 14:09
  • The spectacular difference in execution time between this code and `f1(x);` makes me think that thanks to the low initial repeat counts the JIT compiler can quickly figure out that it can shortcircuit the loop in f1. So, as @erosb says, an effect of the JIT compiler – fvu Oct 12 '15 at 14:10
  • 1
    For some reason these optimizations don't happen when you change `i` to be of type `long`. – Paul Boddington Oct 12 '15 at 14:12

1 Answers1

10

During execution the JVM's just-in-time (JIT) compiler compiles the java bytecode (class format) to the native instruction set of your machine. The JIT performs several optimizations during compilation. In this case the JIT probably realised the followings (just guessing):

  • the f1() method does not have any visible side effects
  • the return value of the f1() call is not stored anywhere

therefore the JIT simply omitted the f1() invocation from the native code. It is possible that after removing the f1() call the entire for(int i = 0; i < x; i++) loop has been removed too (since it also doesn't change program semantics).

erosb
  • 2,943
  • 15
  • 22
  • I love the JIT compiler, although sometimes, on really rare occasions you do need to account for it helping you out and optimizing your code. Especially when doing performance testing. Nice description +1. – Mark W Oct 12 '15 at 14:36