0

Alright so I was working on a game in Eclipse Neon and I noticed that when I added a break statement to the program it significantly slowed down the programs speed from around 120 fps to 80 fps(which makes little sense). So I decided to test it out in another class and got similar results.

This is the code I ran:

public static int[] xArray = new int[100000];
public static int[] yArray = new int[10000];

public static void main(String[] args){

    long timeStart = System.currentTimeMillis();

    int numberOfLoops = 0;
    int uboveMax = 0;

    for(int x = 0; x < xArray.length; x++){
        for(int y = 0; y < yArray.length; y++){
            numberOfLoops++;
            if(y > 9000){
                uboveMax++;
                //break;
            }
        }
    }

    long timeTaken = System.currentTimeMillis();

    System.out.println("Number of Loops: " + numberOfLoops);
    System.out.println("Ubove Max: " + uboveMax);
    System.out.println("Time Taken(MS): " + (timeTaken - timeStart));

}

So when I ran the code (in Eclipse Neon 2 (4.6.2)) I got unexpected results:

With the break statement: Time Taken(MS): 344.8 (average from 5 tests)

Without the break statement: Time Taken(MS): 294.6 (average from 5 tests)

Then when I ran the code (in NetBeans IDE 8.2) I got expected results:

With the break statement: Time Taken(MS): 4.2 (average from 5 tests)

Without the break statement: Time Taken(MS): 556.8 (average from 5 tests)

Shouldn't the code (in Eclipse) with the break statement be running at least the same speed if not even faster? Also what is the cause of the large discrepancy between Eclipse and NetBeans, I know they are very different programs, but don't both run the code from the same JVM, is their something wrong with the Eclipse compiler? If anyone could provide an explanation for this occurrence that would be great, thanks!

Lightning
  • 99
  • 9
  • 4
    That's not how you write a benchmark in Java. Your empty if block is most probably removed by the JIT. – JB Nizet Mar 05 '17 at 09:05
  • Just did an edit, and even when the block is not empty the code still runs slower on average without the break statement. – Lightning Mar 05 '17 at 09:17
  • Better use System.nanoTime(); rather than System.currentTimeMillis(); – azro Mar 05 '17 at 09:24
  • 3
    Again, benchmarking on Java is a very hard task, and requires expertise and good tools (like JMH). So many factors are important, like your VM and platform, how many time you execute the code under test, when the JIT compiles the code, what it can eliminate and optimize, etc. For the record, your benchmark, on *my* machine, takes around 900 millis to execute without the break, and around 10 millis to execute with the break. So the results are completely different from yours. – JB Nizet Mar 05 '17 at 09:30
  • Would a big factor of this outcome be my current Eclipse Version/Software, or would it be difficult to determine the exact factor of this issue? – Lightning Mar 05 '17 at 09:46
  • 3
    Eclipse is mostly irrelevant (unless its Java compiler generates something really different from javac, that wouldn't be optimized the same way). What runs your code is the Java VM. Not eclipse. – JB Nizet Mar 05 '17 at 09:58
  • 1
    Running in the terminal I get 1556ms without the break statement and 6ms with it. Running from Eclipse Neon 2 (4.6.2) I'm getting 390 ms with the break statement and 364 ms without it. Both are using the same Java version. 1.8 from the same source folder. – Chris Sharp Mar 05 '17 at 13:27
  • I tested the same code in NetBeans IDE 8.2 and got around 580ms without the break statement and 4ms with the break statement, so is it possible to conclude that it is a problem with the eclipse compiler, or am I jumping to quick to conclusion? – Lightning Mar 05 '17 at 23:52

1 Answers1

2

This should better be a comment, but it's too long. The problem with your code is that what it does is equivalent to

System.out.println("Number of Loops: " + 1000000000);
System.out.println("Ubove Max: " + 99900000);

This could be optimized down to a few cycles. This doesn't happen as you don't give the JVM enough time and/or because of OSR (see this question for a good example).

You code (without break) could be optimized to

for(int x = 0; x < xArray.length; x++) {
    numberOfLoops += yArray.length;
    uboveMax += Math.max(0, yArray.length - 9001);
}

and further to

numberOfLoops += xArray.length * yArray.length;
uboveMax += xArray.length * Math.max(0, yArray.length - 9001);

The code using break would lead to a similar expression. If I was the JVM, I'd be upset with you wasting time on such a non-sense. The JVM isn't upset, and if you'd gave it a chance, you'd see times close to zero in both cases. It's possible but improbable, that (even given enough time) one of the cases doesn't get optimized as well as the other, but this is nothing essential, it's just that there are countless optimization possibilities and there are cases when the JVM misses something.

IMHO, this example will not give you any insight to why the slowdown happens with your real code. simplifying code in order to locate the problem is good, but you went too far. In reality, your variables do something and probably influence the future computation in way so that breaking out of the loop cases more work to be done in the future. Just guessing, but what else without the real code?

Community
  • 1
  • 1
maaartinus
  • 44,714
  • 32
  • 161
  • 320
  • Thanks for you response, and I know this part of the question was not there when you posted apologies, but what would be the cause of the differences in execution speed between the Eclipse program and NetBeans program, do both programs optimize code differently so it would result in a difference in execution speed? – Lightning Mar 07 '17 at 04:29
  • @Lightning Eclipse and Netbeans compiler (`ecj` and `javac`) differ, but they both do practically no optimizations - it's not their job. All optimizations get done by the JIT which is a part of the JVM and therefore the timings should be the same (as [written here](http://stackoverflow.com/questions/42606407/break-statement-results-in-slower-execution-speed/42608823?noredirect=1#comment72343499_42606407)). If you observe something else, than it's strange, but it will improbably bring you closer to the solution of your real problem. – maaartinus Mar 07 '17 at 04:36