das Keks
das Keks

Reputation: 3941

Performance: greater / smaller than vs not equal to

I wonder if there is a difference in performance between

checking if a value is greater / smaller than another

for(int x = 0; x < y; x++); // for y > x

and

checking if a value is not equal to another

for(int x = 0; x != y; x++); // for y > x

and why?

In addition: What if I compare to zero, is there a further difference?

It would be nice if the answers also consider an assebled view on the code.

EDIT: As most of you pointed out the difference in performance of course is negligible but I'm interested in the difference on the cpu level. Which operation is more complex?

To me it's more a question to learn / understand the technique.

I removed the Java tag, which I added accidentally because the question was meant generally not just based on Java, sorry.

Upvotes: 52

Views: 25063

Answers (7)

Lohith S
Lohith S

Reputation: 89

The performance in theory is the same. When you do a less than or not equal to operation, in the processor level you actually perform a subtract operation and check if the negative flag or zero flag is enabled in the result. In theory the performance will be the same. Since the difference is only checking the flag set.

Upvotes: 3

das Keks
das Keks

Reputation: 3941

Now 6 years later and after still receiving occasional notifications from this question I'd like to add some insights that I've gained during my computer science study.

Putting the above statements into a small program and compiling it...

public class Comp {
    public static void main(String[] args) {
        int y = 42;

        for(int x = 0; x < y; x++) {
            // stop if x >= y
        }

        for(int x = 0; x != y; x++) {
            // stop if x == y
        }
    }
}

... we get the following bytecode:

  public static void main(java.lang.String[]);
    Code:
       // y = 42
       0: bipush        42  
       2: istore_1

       // first for-loop
       3: iconst_0
       4: istore_2
       5: iload_2
       6: iload_1
       7: if_icmpge     16      // jump out of loop if x => y
      10: iinc          2, 1
      13: goto          5

       // second for-loop
      16: iconst_0
      17: istore_2
      18: iload_2
      19: iload_1
      20: if_icmpeq     29      // jump out of loop if x == y
      23: iinc          2, 1
      26: goto          18

      29: return

As we can see, on bytecode level both are handled in the same way and use a single bytecode instruction for the comparison.

As already stated, how the bytecode is translated into assembler/machine code depends on the JVM. But generally this conditional jumps can be translated to some assembly code like this:

; condition of first loop
CMP eax, ebx
JGE label  ; jump if eax > ebx

; condition of second loop
CMP eax, ebx
JE  label  ; jump if eax == ebx

On hardware level JGE and JE have the same complexity.

So all in all: Regarding performance, both x < y and x != y are theoretically the same on hardware level and one isn't per se faster or slower than the other.

Upvotes: 20

aetherwalker
aetherwalker

Reputation: 131

Other people seem to have answered from a measured perspective, but from the machine level you'd be interested in the Arithmetic Logic Unit (ALU), which handles the mathy bits on a "normal computer". There seems to be a pretty good detail in How does less than and greater than work on a logical level in binary? for complete details.

From purely a logical level, the short answer is that it's easier to tell if something is not something than it is to tell if something is relative to something, however this has likely been optimized in your standard personal computer or server, so you'll only see actual gains likely in small personal builds like on-board computers for drones or other micro-technologies.

Upvotes: 5

Macrofeet
Macrofeet

Reputation: 1

Wonder if nested for each test, same results ?

for(int x = 0; x < y; x++)
{   
  for(int x2 = 0; x2 < y; x2++)  {}   
}

for(int x = 0; x != y; x++)
{
  for(int x2 = 0; x2 != y; x2++) {}    
}

Upvotes: -5

James Dunn
James Dunn

Reputation: 8284

The performance is absolutely negligible. Here's some code to prove it:

public class OpporatorPerformance {
    static long y = 300000000L;

    public static void main(String[] args) {
        System.out.println("Test One: " + testOne());
        System.out.println("Test Two: " + testTwo());
        System.out.println("Test One: " + testOne());
        System.out.println("Test Two: " + testTwo());
        System.out.println("Test One: " + testOne());
        System.out.println("Test Two: " + testTwo());
        System.out.println("Test One: " + testOne());
        System.out.println("Test Two: " + testTwo());

    }

    public static long testOne() {
        Date newDate = new Date();
        int z = 0;
        for(int x = 0; x < y; x++){ // for y > x
            z = x;
        }
        return new Date().getTime() - newDate.getTime();
    }

    public static long testTwo() {
        Date newDate = new Date();
        int z = 0;
        for(int x = 0; x != y; x++){ // for y > x
            z = x;
        }
        return new Date().getTime() - newDate.getTime();
    }

}

The results:

Test One: 342
Test Two: 332
Test One: 340
Test Two: 340
Test One: 415
Test Two: 325
Test One: 393
Test Two: 329

Upvotes: 16

Peter Lawrey
Peter Lawrey

Reputation: 533820

You should still do what is clearer, safer and easier to understand. These micro-tuning discussions are usually a waste of your time because

  • they rarely make a measurable difference
  • when they make a difference this can change if you use a different JVM, or processor. i.e. without warning.

Note: the machine generated can also change with processor or JVM, so looking this is not very helpful in most cases, even if you are very familiar with assembly code.

What is much, much more important is the maintainability of the software.

Upvotes: 41

OldCurmudgeon
OldCurmudgeon

Reputation: 65869

There is rarely a performance hit but the first is much more reliable as it will handle both of the extraordinary cases where

  1. y < 0 to start
  2. x or y are messed with inside the block.

Upvotes: 5

Related Questions