4

Someone told me its faster to do this

if(null == object) 

vs doing this

if(object == null)

I think theres no difference. Please confirm the efficiency/performance is the same.

Note... my friend did a performance test already to prove that the first is slightly faster.

update on why some do it this way: say you accidentally do an assignment with " = " instead of the intended equality check such as "==", the first will give a compiler error if you use null first. so gramatically it is better.

j2emanue
  • 60,549
  • 65
  • 286
  • 456
  • 6
    How about you confirm by writing a test program and time the difference? Or look at the generated bytecode. – OldProgrammer Jul 21 '14 at 21:46
  • Maybe the question could be generalized to other interesting assignments or comparisons. – NoDataDumpNoContribution Jul 21 '14 at 21:47
  • i dont get why im getting a down vote. I ran the test by Chechus and i indeed see a difference although its not a performance impact. That was my only quesiton. What if i had 3 thousand checks like this ? then i'd like to know the impact. Thats all i wanted to know. – j2emanue Jul 21 '14 at 21:54
  • @OldProgrammer Don't these optimizations happen at runtime? Any reason to look up bytecode? – Swapnil Jul 21 '14 at 21:54
  • I attached a profiler to a program to test this. It looks like the rumor that the OP heard is actually true, at least on my machine. I couldn't fit the results into a comment, so I posted my own answer. If anyone can explain the results I got, feel free to use my results in your own answer and then let me know so I can delete mine. – Rainbolt Jul 21 '14 at 22:00
  • @j2emanue It would have been better if you would have mentioned the performance test you carried out in the question itself. – Swapnil Jul 21 '14 at 22:01

8 Answers8

15

I'll build on top of @James answer:

public class TestNull {
   public void left(String s) {
       if (s == null);
   }
   public void right(String s) {
       if (null == s);
   }
}

bytecode:

public class TestNull {
  ....
  public void left(java.lang.String);
    Code:
       0: aload_1       
       1: ifnonnull     4
       4: return        

  public void right(java.lang.String);
     Code:
       0: aconst_null   
       1: aload_1       
       2: if_acmpne     5
       5: return        
}

First is faster (when null is on the right hand side) because java has a bytecode command ifnonnull which compares the loaded variable with null.

Second is slower because another command is being used: if_acmpne and it compares the loaded aconst_null which it sees as a constant.

Apparently if_acmpne is slower than ifnonnull:

if_acmpne pops the top two object references off the stack and compares them. If the two object references are not equal (i.e. if they refer to different objects), execution branches to the address (pc + branchoffset), where pc is the address of the if_acmpne opcode in the bytecode and branchoffset is a 16-bit signed integer parameter following the if_acmpne opcode in the bytecode. If the object references refer to the same object, execution continues at the next instruction.

ifnonnull pops the top object reference off the operand stack. If the object reference is not the special null reference, execution branches to the address (pc + branchoffset), where pc is the address of the ifnonnull opcode in the bytecode and branchoffset is a 16-bit signed integer parameter following the ifnonnull opcode in the bytecode. If the object reference on the stack is null, execution continues at the next instruction.

So if (s == null) must be faster (opposite to what OP stated in the question).

ACV
  • 9,964
  • 5
  • 76
  • 81
  • 1
    This should be the accepted answer. Not some answer where somebody runs a method once and has no basis for his claims. +1 for including Java bytecode as a proper explanation. – searchengine27 Sep 05 '18 at 18:30
  • 1
    @searchengine27 My answer is the accepted answer, and I think you might have confused it for another. I ran the two methods tens of thousands of times. I have experimental results as a basis for my claims. When you generate bytecode and reason about which bytecode should be faster, that's called a theoretical result. Experimental results are what actually happen when you perform the task. Both kinds of results are important. – Rainbolt Sep 11 '18 at 14:10
12

I wrote a program to test this. All it does it call two methods repeatedly. The only contents of the methods are the two comparisons we want to test the performance of.

public class StackOverflow {
    public static void main(String[] args) {
        String s = "";
        while (true) {
            a(s);
            b(s);
        }
    }
    private static void a(String s) {
        if (s == null);
    }
    private static void b(String s) {
        if (null == s);
    }
}

I attached a profiler to my program. Here are the results after 70 seconds of execution:

enter image description here

As you can see, the CPU time is nearly four times lighter in a(). This suggests that the comparison s == null is indeed faster than null == s.

Sergio
  • 3,317
  • 5
  • 32
  • 51
Rainbolt
  • 3,542
  • 1
  • 20
  • 44
  • 1
    comparing this to my test, looks like JIT makes his work and optimizes, because my test is consistently opposite to this result (see my answer below)! – Sergio Jul 21 '14 at 22:15
  • 1
    Using the same code, with Oracle's 1.7 JRE, and attaching the profiler after that code has been running for awhile, I get equivalent results for both. – Andy Thomas Jul 21 '14 at 22:18
  • 1
    When you sample CPU utilisation, the sampler will give you an estimate which can be consistently wrong for simple examples. In your case, it appears that both methods are eliminated as they don't do anything. – Peter Lawrey Jul 21 '14 at 22:22
  • 1
    The profiler image you included is the opposite of your last paragraph - a=39.9ms, b=151 ms. – Andy Thomas Jul 21 '14 at 22:22
  • @Chechus It looks like you ran your test once. Mine runs tens of thousands of times over a period of 70 seconds. I like to think that gives a better estimate. – Rainbolt Jul 21 '14 at 23:56
  • 1
    @PeterLawrey What is an operation that 1) wouldn't be optimized into oblivion and 2) wouldn't completely overpower the results of the test? Even a simple `System.out.println("a");` was so expensive that the difference between methods was negligible compared to the time it took to print. – Rainbolt Jul 21 '14 at 23:58
  • @Rainbolt I agree. I would also expect a short method like this to be inlined in an unprofiled application as it will be less than 35 bytes. – Peter Lawrey Jul 22 '14 at 00:22
2

I'm testing with this code:

public class TestNull {
   public void left(String s) {
       if (s == null);
   }
   public void right(String s) {
       if (null == s);
   }
}

I compiled it with javac 1.8.0_05, and then inspected the bytecode:

public class TestNull {
  ....
  public void left(java.lang.String);
    Code:
       0: aload_1       
       1: ifnonnull     4
       4: return        

  public void right(java.lang.String);
     Code:
       0: aconst_null   
       1: aload_1       
       2: if_acmpne     5
       5: return        
}

Apparently, the left only pushes and pops 1 variable on the stack while right pushes and pops 2.

I'm not sure about the performance difference between ifnonnull and if_acmpne, but if there is none, then I guess although there is NOT MUCH difference, the "right" comparison should be slower for doing more work on the stack.

However, could somebody enlighten me why the compiler doesn't rewrite the code?

James
  • 537
  • 3
  • 11
2

This is purely a stylistic difference. In my test I get a long run for the first test case which can be attributed to JRE setup; the rest of the iterations show that they are identical.

        for( int j = 0; j < 10; j++ )
        {
            Object a = null;
            int i = 0;
            long tik = System.nanoTime();
            while( i < 500000 )
                if( a == null )
                    i++;
            System.out.print( "a:" + (System.nanoTime() - tik) );
            Object b = null;
            i = 0;
            tik = System.nanoTime();
            while( i < 500000 )
                if( null == b )
                    i++;
            System.out.println( " b:" + (System.nanoTime() - tik) );
        }

With the following results:

a:826735 b:354261
a:318150 b:314729
a:323472 b:314729
a:314350 b:315869
a:318151 b:316630
a:325753 b:314350
a:316250 b:314350
a:314730 b:321952
a:398733 b:340197
a:328794 b:338676
LINEMAN78
  • 2,562
  • 16
  • 19
1

There's really not much significant difference between these two expressions, they run equally fast. If at all there's a difference, I don't think it's worth the effort.

The only reason people write the non-variable operand first is to avoid accidental (still syntactically correct) usage of assignment operator in languages like C. Those who've migrated to Java from those languages might be continuing the practice.

Swapnil
  • 8,201
  • 4
  • 38
  • 57
0

There shouldn't be a difference. That notation arose due to many people using the assignment operator instead of the comparison operator, which lead to many hard to find bugs. For example:

if(null = object) {
    //compiler throws error that you can't assign null
}

edit: As Jon pointed out, this is possible in other languages. My guess is that the habit carried over to Java land.

telkins
  • 10,440
  • 8
  • 52
  • 79
  • 4
    Well, the notation arose due to people making assignment mistakes *in other languages*. `if (object = null) {` is invalid in Java too... – Jon Skeet Jul 21 '14 at 21:50
  • @JonSkeet True, I think people's habits just carried over to Java. – telkins Jul 21 '14 at 21:51
0
@Test
public void testNullCheck() throws Exception {
    Object o = null;

    long i1 = System.nanoTime();
    if (null == o) {
    }
    long t1 = System.nanoTime() - i1;

    long i2 = System.nanoTime();
    if (o == null) {
    }
    long t2 = System.nanoTime() - i2;

    assertThat(t1).isGreaterThan(t2);
}

Where in my JVM :

T2 :116L
T1 :304L

So yes, there is a difference, at least in the practice.


EDIT:

Please confirm the efficiency/performance is the same.

Nope, is not the same. But given the existence of JIT over the time COULD be the same, a new test is needed where JIT should be taken in to the account.

Sergio
  • 3,317
  • 5
  • 32
  • 51
  • Not the downvoter. But its always worth including a warmup phase when benchmarking or else you can end up with the compile phase in the middle of your test. Also; is this run only once? Its necessary to run tens of thousands of tests and average the results to get meaningful results – Richard Tingle Jul 21 '14 at 22:20
  • 1
    Wasn't me, but it could certainly be that you've claimed superior performance for a method (one that's very fast and highly likely to be affected by both compiler and JIT optimizations) based on timing a single iteration on a machine running an OS that's almost certainly time-slicing, which means your conclusion means precisely nothing in either direction. It doesn't mean your conclusion is right, or that it's wrong, just that your test as described does nothing whatsoever to prove it. – Tim Jul 21 '14 at 22:23
-2

if(null == object) and if(object == null) both are same. They both have same performance and hence, switching order doesn't matter for this two expression.

user2737926
  • 97
  • 1
  • 1
  • 9
  • 1
    until you know how bytecode works and then realize that there are optimized instruction sets for certain grammars that are functionally equivalent. – Ajax Apr 02 '18 at 21:10