Java ' ... != null' 或 'null != ....' 最佳性能?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2398588/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 07:02:09  来源:igfitidea点击:

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

javaperformancemicro-optimization

提问by asela38

I wrote two methods to check there performance

我写了两种方法来检查那里的性能

 public class Test1 {

 private String value;

 public void notNull(){
  if( value != null) {
    //do something
  }
}

public void nullNot(){
 if( null != value) {
  //do something
 }
}

}

and checked it's byte code after compiling

并在编译后检查它的字节码

public void notNull();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: getfield #2; //Field value:Ljava/lang/String;
4: ifnull 7
7: return
LineNumberTable: 
line 6: 0
line 9: 7

StackMapTable: number_of_entries = 1
frame_type = 7 /* same */


public void nullNot();
Code:
Stack=2, Locals=1, Args_size=1
0: aconst_null
1: aload_0
2: getfield #2; //Field value:Ljava/lang/String;
5: if_acmpeq 8
8: return
LineNumberTable: 
line 12: 0
line 15: 8

StackMapTable: number_of_entries = 1
frame_type = 8 /* same */


}

in here two opcodes are used to implement the if condition: in first case it use ifnull- check top value of stack is null-, and in second case it use if_acmpeq- check top two value are equal in the stack-

在这里,两个操作码用于实现 if 条件:在第一种情况下它使用 ifnull-检查栈顶值是否为空-,在第二种情况下它使用 if_acmpeq-检查栈顶两个值是否相等-

so, will this make an effect on performance? (this will helps me to prove first implementation of null is good in performance wise as well as in the aspect of readability :) )

那么,这会影响性能吗?(这将帮助我证明 null 的首次实现在性能和可读性方面都很好:))

采纳答案by polygenelubricants

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.

比较生成的字节码几乎没有意义,因为大部分优化都是在运行时使用 JIT 编译器进行的。我猜在这种情况下,任何一个表达式都同样快。如果有任何差异,则可以忽略不计。

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

这不是您需要担心的事情。寻找大图优化。

回答by Anthony Forloney

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

null第一似乎产生额外的字节码,但除了有可能不是一个性能差异。

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.

我会使用这种notNull()方法,这样如果您忘记!并意外键入null = value.

回答by Cam

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

如果速度(或内存/无论情况如何)增益可以忽略不计,请不要以牺牲可读性为代价进行优化。我认为!=null通常更具可读性,所以使用它。

回答by Matthew H

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

差异可以忽略不计,所以选择最易读的(!= nullimo)

回答by Michael Mao

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.

哦,如果您要求终极性能,请不要创建额外的类或方法。即使是静态方法也需要一些时间,因为 Java 类加载器需要 JIT 加载它。

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.

坦率地说,我认为选择两者之一的性能奖励很容易被引入不必要的方法的开销所抵消。

回答by Michael D. Irizarry

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

为了可读性,我会坚持使用 (value != null)。但是你总是可以使用断言。

回答by seh

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 morereadable because it puts the crucial value in the most prominent position.

除了在 C 中避免意外赋值的来之不易的智慧,它有利于将常量放在二元运算符的左侧,我发现左侧的常量更具可读性,因为它将关键值放在最突出的位置。

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 switchand case: given thisvariable, select a matching value. Seeing the value on the left, one focuses on the particular condition being selected.

通常一个函数体将只使用几个变量,并且通常通过上下文可以明显看出哪个变量正在被检查。通过将常量放在左侧,我们更接近地模仿switchcase: 给定这个变量,选择一个匹配的值。看到左侧的值,可以重点关注所选择的特定条件。

When I scan

当我扫描

if (var == null)

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

我读它为,“我们在var这里检查,我们正在比较它的平等性,与......啊,空值。” 相反,当我扫描

if (null == var)

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

我想,“我们正在查看一个值是否为空,并且......是的,var我们正在检查它。” 这是一种更强烈的认可

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.

看到字节码的差异令人着迷。感谢分享。

回答by Humphrey Bogart

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

像这样的分钟优化是编译器的工作,尤其是在像 Java 这样的高级语言中。

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

虽然严格来说它与这里无关,但不要过早优化!

回答by Rex Kerr

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:

有了这样的问题,很难知道 JVM 会有多聪明(尽管答案是“如果可能的话通常非常聪明”,在这种情况下看起来很有可能)。但为了确定起见,请对其进行测试:

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.)

所以答案是:不,根本没有有意义的区别。(并且 JIT 编译器可以找到额外的技巧来在相同数量的重复运行后加快速度。)



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.

更新:上面的代码运行了一个特别的基准测试。使用JMH(现在它存在!)是帮助避免(某些)微基准测试陷阱的好方法。上面的代码避免了最糟糕的陷阱,但它没有给出明确的错误估计,并忽略了有时很重要的各种其他事情。这些天:使用 JMH!此外,如有疑问,请运行您自己的基准测试。细节有时很重要——对于像这样简单的事情来说并不常见,但如果它对你来说真的很重要,你应该检查一个尽可能接近生产的条件,你可以管理。

回答by gmhk

You can ignore this very minute optimisation stuff during coding

您可以在编码期间忽略这些非常细微的优化内容