Which of these pieces of code is faster in Java?

前端 未结 16 1938
囚心锁ツ
囚心锁ツ 2020-11-30 04:25

a) for(int i = 100000; i > 0; i--) {}

b) for(int i = 1; i < 100001; i++) {}

The answer is t

相关标签:
16条回答
  • 2020-11-30 04:57

    Are you sure that the interviewer who asks such a question expects a straight answer ("number one is faster" or "number two is faster"), or if this question is asked to provoke a discussion, as is happening in the answers people are giving here?

    In general, it's impossible to say which one is faster, because it heavily depends on the Java compiler, JRE, CPU and other factors. Using one or the other in your program just because you think that one of the two is faster without understanding the details to the lowest level is superstitious programming. And even if one version is faster than the other on your particular environment, then the difference is most likely so small that it's irrelevant.

    Write clear code instead of trying to be clever.

    0 讨论(0)
  • 2020-11-30 04:59

    I've been making tests for about 15 minutes now, with nothing running other than eclipse just in case, and I saw a real difference, you can try it out.

    When I tried timing how long java takes to do "nothing" and it took around 500 nanoseconds just to have an idea.

    Then I tested how long it takes to run a for statement where it increases:

    for(i=0;i<100;i++){}

    Then five minutes later I tried the "backwards" one:

    for(i=100;i>0;i--)

    And I've got a huge difference (in a tinny tiny level) of 16% between the first and the second for statements, the latter being 16% faster.

    Average time for running the "increasing" for statement during 2000 tests: 1838 n/s

    Average time for running the "decreasing" for statement during 2000 tests: 1555 n/s

    Code used for such tests:

    public static void main(String[] args) {
        long time = 0;  
        for(int j=0; j<100; j++){
        long startTime = System.nanoTime();
        int i;
            /*for(i=0;i<100;i++){
    
            }*/
            for(i=100;i>0;i--){
    
            }
        long endTime = System.nanoTime();
        time += ((endTime-startTime));
        }
        time = time/100;
        System.out.print("Time: "+time);
    }
    

    Conclusion: The difference is basically nothing, it already takes a significant amount of "nothing" to do "nothing" in relation to the for statement tests, making the difference between them negligible, just the time taken for importing a library such as java.util.Scanner takes way more to load than running a for statement, it will not improve your application's performance significantly, but it's still really cool to know.

    0 讨论(0)
  • 2020-11-30 05:00

    With regards for testing for zero in the JVM: it can apparently be done with ifeq whereas testing for anything else requires if_icmpeq which also involves putting an extra value on the stack.

    Testing for > 0, as in the question, might be done with ifgt, whereas testing for < 100001 would need if_icmplt.

    0 讨论(0)
  • 2020-11-30 05:03

    I decided to bite and necro back the thread.

    both of the loops are ignored by the JVM as no-ops. so essentially even one of the loops were till 10 and the other till 10000000, there would have been no difference.

    Looping back to zero is another thing (for jne instruction but again, it's not compiled like that), the linked site is plain weird (and wrong).

    This type of a question doesn't fit any JVM (nor any other compiler that can optimize).

    0 讨论(0)
  • 2020-11-30 05:03

    The loops are identical, except for one critical part:

    i > 0; and i < 100001;

    The greater than zero check is done by checking the NZP (Commonly known as condition code or Negative Zero or Positive bit) bit of the computer.

    The NZP bit is set whenever operation such as load, AND, addition ect. are performed.

    The greater than check cannot directly utilize this bit (and therefore takes a bit longer...) The general solution is to make one of the values negative (by doing a bitwise NOT and then adding 1) and then adding it to the compared value. If the result is zero, then they're equal. Positive, then the second value (not the neg) is greater. Negative, then the first value (neg) is greater. This check takes a slightly longer than the direct nzp check.

    I'm not 100% certain that this is the reason behind it though, but it seems like a possible reason...

    0 讨论(0)
  • 2020-11-30 05:05

    Typically real code will run faster counting upwards. There are a few reasons for this:

    • Processors are optimised for reading memory forwards.
    • HotSpot (and presumably other bytecode->native compilers) heavily optimise forward loops, but don't bother with backward loops because they happen so infrequently.
    • Upwards is usually more obvious, and cleaner code is often faster.

    So happily doing the right thing will usually be faster. Unnecessary micro-optimisation is evil. I haven't purposefully written backward loops since programming 6502 assembler.

    0 讨论(0)
提交回复
热议问题