' … != null' or 'null != …' best performance?

风流意气都作罢 提交于 2019-11-27 07:33:33

Comparing the generated bytecodes is mostly meaningless, since most of the optimization happens in run time with the JIT compiler. I'm going to guess that in this case, either expression is equally fast. If there's any difference, it's negligible.

This is not something that you need to worry about. Look for big picture optimizations.

Don't optimize at the expense of readability if the speed (or memory/whatever the case may be) gain will be negligible. I think !=null is generally more readable, so use that.

With questions like this, it's hard to know how smart the JVM will be (though the answer is "usually pretty smart if possible" and it looks very possible in this case). But just to be sure, test it:

class Nullcheck {
  public static class Fooble { }

  Fooble[] foo = {null , new Fooble(), null , null,
                  new Fooble(), null, null, new Fooble() };

  public int testFirst() {
    int sum = 0;
    for (int i=0 ; i<1000000000 ; i++) if (foo[i&0x7] != null) sum++;
    return sum;
  }

  public int testSecond() {
    int sum = 0;
    for (int i=0 ; i<1000000000 ; i++) if (null != foo[i&0x7]) sum++;
    return sum;
  }

  public void run() {
    long t0 = System.nanoTime();
    int s1 = testFirst();
    long t1 = System.nanoTime();
    int s2 = testSecond();
    long t2 = System.nanoTime();
    System.out.printf("Difference=%d; %.3f vs. %.3f ns/loop (diff=%.3f)\n",
      s2-s1,(t1-t0)*1e-9,(t2-t1)*1e-9,(t0+t2-2*t1)*1e-9);
  }

  public static void main(String[] args) {
    Nullcheck me = new Nullcheck();
    for (int i=0 ; i<5 ; i++) me.run();
  }
}

And on my machine this yields:

Difference=0; 2.574 vs. 2.583 ns/loop (diff=0.008)
Difference=0; 2.574 vs. 2.573 ns/loop (diff=-0.001)
Difference=0; 1.584 vs. 1.582 ns/loop (diff=-0.003)
Difference=0; 1.582 vs. 1.584 ns/loop (diff=0.002)
Difference=0; 1.582 vs. 1.582 ns/loop (diff=0.000)

So the answer is: no, no meaningful difference at all. (And the JIT compiler can find extra tricks to speed each up after the same number of repeat runs.)


Update: The code above runs an ad-hoc benchmark. Using JMH (now that it exists!) is a good way to help avoid (some) microbenchmarking pitfalls. The code above avoids the worst pitfalls but it doesn't give explicit error estimates and ignores various other things that sometimes matter. These days: use JMH! Also, when in doubt, run your own benchmarks. Details sometimes matter — not very often for something as straightforward as this, but if it is really important to you you should check in a condition as close to production as you can manage.

Apart from the hard-earned wisdom of avoiding accidental assignment in C, which favors putting the constant on the left of the binary operator, I find the constant on the left to be more readable because it puts the crucial value in the most prominent position.

Usually a function body will use only a few variables, and it's usually apparent by way of context which variable is under inspection. By putting the constant on the left, we more closely mimic switch and case: given this variable, select a matching value. Seeing the value on the left, one focuses on the particular condition being selected.

When I scan

if (var == null)

I read it as, "We're inspecting var here, and we're comparing it for equality, against ... ah, null." Conversely, when I scan

if (null == var)

I think, "We're seeing if a value is null, and ... yes, it's var we're inspecting." It's an even stronger recognition with

if (null != var)

which my eye just picks up on immediately.

This intuition comes from consistency of habit, preferring to read what one writes, and writing what one prefers to read. One can learn it either way, but it's not objectively true as others have answered here that putting the variable on the left is clearer. It depends on what aspect of the expression one wants to be most clear first.

Seeing the bytecode difference was fascinating. Thanks for sharing that.

The difference will be negligable so go with what's most readable (!= null imo)

I'd stick with (value != null) for readability. But you can always use Assertions.

Minute optimization like that is the job of the compiler, especially in high-level languages like Java.

Although strictly it's not relevant here, don't optimize prematurely!

From the point of view, there is no significant difference in performance.

However, it is useful to write the null first to catch typos errors.

For example, if you are used to write this code:

if (obj == null)

Could be wrote by mistake as:

if (obj = null)

From the point of view of the compiler, this is fine.

However, If you are used to write the code as:

if (null == obj)

and made the mistake to write:

if (null = obj)

the compiler will let you know you made a mistake in that line.

Putting null first seems to generate an extra byte-code, but aside from that there may not be a performance difference.

Personally, I wouldn't worry about performance until its time to worry about performance.

I would use the notNull() approach, just so you don't throw a compiler error if you forget the ! and accidentally type null = value.

Oh, if you ask for ultimate performance, don't create additional class or methods. Even static methods would take a bit of time as the Java class loader needs to JIT load it.

So, whenever you need to check if a variable is null, you just test it by either

if (x == null)

or

if (null == x)

Frankly I reckon the performance bonus to pick one of the two is easily offset by the overhead of introducing unnecessary methods.

You can ignore this very minute optimisation stuff during coding

As you can see the performance different is very less. Don't worry about the small things it is always better to focus more on algorithm. And obviously readability is a factor.

I would use the "new" Java 8 feature, I write several examples:

import java.util.Optional;

public class SillyExample {

public void processWithValidation(final String sampleStringParameter){
    final String sampleString = Optional.ofNullable(sampleStringParameter).orElseThrow(() -> new IllegalArgumentException("String must not be null"));

    //Do what you want with sampleString
}


public void processIfPressent(final String sampleStringParameter){
    Optional.ofNullable(sampleStringParameter).ifPresent(sampleString -> {

        //Do what you want with sampleString

    });

}

public void processIfPressentWithFilter(final String sampleStringParameter){
    Optional.ofNullable(sampleStringParameter).filter("hello"::equalsIgnoreCase).ifPresent(sampleString -> {

        //Do what you want with sampleString

    });

}

}

Anton Balaniuc

In Java-8 two additional methods were introduced to Objects class: Objects#nonNull and Objects#isNull, which you can use to replace null checks. An interesting things is that both of them use objects first:

public static boolean isNull(Object obj) {
    return obj == null;
}

and

public static boolean nonNull(Object obj) {
    return obj != null;
}

correspondingly. I guess it means that this is the recommended way (at least core jdk developers used that approach) Objects source code

I would prefer null != object as it makes clearly visible that it's just for null check.

Byte code is just a simple translation of the source code.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!