Skip to main content

Java efficiency


I'm playing with some piece of code calculating the time needed to compute some Java code to get a feeling of the efficiency or inefficiency of some of Java's functionality. Doing so I'm stuck now with some really strange effect I just can't explain myself. Maybe someone of you can help me understand it.




public class PerformanceCheck {

public static void main(String[] args) {
List<PerformanceCheck> removeList = new LinkedList<PerformanceCheck>();

int maxTimes = 1000000000;

for (int i=0;i<10;i++) {
long time = System.currentTimeMillis();

for (int times=0;times<maxTimes;times++) {
// PERFORMANCE CHECK BLOCK START

if (removeList.size() > 0) {
testFunc(3);
}

// PERFORMANCE CHECK BLOCK END
}

long timeNow = System.currentTimeMillis();
System.out.println("time: " + (timeNow - time));
}
}

private static boolean testFunc(int test) {
return 5 > test;
}

}



Starting this results in a relatively long computation time (remember removeList is empty, so testFunc is not even called):




time: 2328
time: 2223
...



While replacing anything of the combination of removeList.size() > 0 and testFunc(3) with anything else has better results. For example:




...
if (removeList.size() == 0) {
testFunc(3);
}
...



Results in (testFunc is called every single time):




time: 8
time: 7
time: 0
time: 0



Even calling both functions independent from each other results in the lower computation time:




...
if (removeList.size() == 0);
testFunc(3);
...



Result:




time: 6
time: 5
time: 0
time: 0
...



Only this particular combination in my initial example takes so long. This is irritating me and I'd really like to understand it. What's so special about it?



Thanks.



Addition:



Changing testFunc() in the first example




if (removeList.size() > 0) {
testFunc(times);
}



to something else, like




private static int testFunc2(int test) {
return 5*test;
}



Will result in being fast again.


Source: Tips4allCCNA FINAL EXAM

Comments

  1. That is really surprising. The generated bytecode is identical except for the conditional, which is ifle vs ifne.

    The results are much more sensible if you turn off the JIT with -Xint. The second version is 2x slower. So it's to do with what the JIT optimization.

    I assume that it can optimize out the check in the second case but not the first (for whatever reason). Even though it means it does the work of the function, missing that conditional makes things much faster. It avoids pipeline stalls and all that.

    ReplyDelete
  2. Well, I am glad not having to deal with Java performance optimizations. I tried it myself with Java JDK 7 64-Bit. The results are arbitrary ;). It makes no difference which lists I am using or if I cache the result of size() before entering the loop. Also entirely wiping out the test function makes almost no difference (so it can't be a branch prediction hit either).
    Optimization flags improve performance but are as arbitrary.

    The only logical consequence here is that the JIT compiler sometimes is able to optimize away the statement (which is not that hard to be true), but it seems rather arbitrary. One of the many reasons why I prefer languages like C++, where the behaviour is at least deterministic, even if it is sometimes arbitrary.

    BTW in the latest Eclipse, like it always was on Windows, running this code via IDE "Run" (no debug) is 10 times slower than running it from console, so much about that...

    ReplyDelete
  3. When the runtime compiler can figure out testFunc evaluates to a constant, I believe it does not evaluate the loop, which explains the speedup.

    When the condition is removeList.size() == 0 the function testFunc(3) gets evaluated to a constant. When the condition is removeList.size() != 0 the inner code never gets evaluated so it can't be sped-up. You can modify your code as follows:

    for (int times = 0; times < maxTimes; times++) {
    testFunc(); // Removing this call makes the code slow again!
    if (removeList.size() != 0) {
    testFunc();
    }
    }

    private static boolean testFunc() {
    return testFunc(3);
    }


    When testFunc() is not initially called, the runtime compiler does not realize that testFunc() evaluates to a constant, so it cannot optimize the loop.

    Certain functions like

    private static int testFunc2(int test) {
    return 5*test;
    }


    the compiler likely tries to pre-optimize (before execution), but apparently not for the case of an parameter is passed in as an integer and evaluated in a conditional.

    Your benchmark returns times like

    time: 107
    time: 106
    time: 0
    time: 0
    ...


    suggesting that it takes 2 iterations of the outer-loop for the runtime compiler to finish optimizing. Compiling with the -server flag would probably return all 0's in the benchmark.

    ReplyDelete
  4. These benchmarks are tough since compilers are so darned smart. One guess: Since the result of testFunc() is ignored, the compiler might be completely optimizing it out. Add a counter, something like

    if (testFunc(3))
    counter++;


    And, just for thoroughness, do a System.out.println(counter) at the end.

    ReplyDelete
  5. The times are unrealistically fast per iteration. This means the JIT has detected that your code doesn't do anything and has eliminated it. Subtle changes can confuse the JIT and it can't determine the code doesn't do anything and it takes some time.

    If you change the test to do something marginally useful, the difference will disappear.

    ReplyDelete

Post a Comment

Popular posts from this blog

Why is this Javascript much *slower* than its jQuery equivalent?

I have a HTML list of about 500 items and a "filter" box above it. I started by using jQuery to filter the list when I typed a letter (timing code added later): $('#filter').keyup( function() { var jqStart = (new Date).getTime(); var search = $(this).val().toLowerCase(); var $list = $('ul.ablist > li'); $list.each( function() { if ( $(this).text().toLowerCase().indexOf(search) === -1 ) $(this).hide(); else $(this).show(); } ); console.log('Time: ' + ((new Date).getTime() - jqStart)); } ); However, there was a couple of seconds delay after typing each letter (particularly the first letter). So I thought it may be slightly quicker if I used plain Javascript (I read recently that jQuery's each function is particularly slow). Here's my JS equivalent: document.getElementById('filter').addEventListener( 'keyup', function () { var jsStart = (new Date).getTime()...

Is it possible to have IF statement in an Echo statement in PHP

Thanks in advance. I did look at the other questions/answers that were similar and didn't find exactly what I was looking for. I'm trying to do this, am I on the right path? echo " <div id='tabs-".$match."'> <textarea id='".$match."' name='".$match."'>". if ($COLUMN_NAME === $match) { echo $FIELD_WITH_COLUMN_NAME; } else { } ."</textarea> <script type='text/javascript'> CKEDITOR.replace( '".$match."' ); </script> </div>"; I am getting the following error message in the browser: Parse error: syntax error, unexpected T_IF Please let me know if this is the right way to go about nesting an IF statement inside an echo. Thank you.