检查布尔值比在java中设置布尔值更快?

这个:

if (var) { var = false; } 

对此:

 var = false; 

有速度差吗?

有几件事情发挥作用,对实际性能的最终影响是您需要根据用例来衡量的。 我认为这是你发现的一种方法很多:

  1. 分支预测 – 如果var几乎总是假的,这就是代码所暗示的,分支预测器几乎总是正确的。 如果该字段经常变化,那么这将成为一个经常被错误预测的分支并且将是昂贵的。

  2. 读取未命中 – 如果var主要是读取(并且读取很多),那么避免无故更改可以帮助您的软件不会使其所在的缓存行无效。 如果你写它的每个其他核心读取它(以及同一缓存行上的任何内容)将需要获得一个新的副本遇到读取错过。 这意味着为了使读取具有更一致的速度,上述方法可能值得变慢。

  3. 写入成本与读取成本 – 如果var是易失性的,那么它的写入是一个非常昂贵的LoadStore屏障。 相比之下,读取volatile(一个LoadLoad屏障)相当便宜(对于经常使用且几乎没有改变的值的缓存命中)。 相比之下,这可以使分支非常便宜。

这是人们的优化,可以在JDK(IIRC)中找到示例,我假设您有理由考虑它。

一个代码包含一个比较,因此您的编译器可能会生成一个类似于以下内容的java字节码:

  public static void main(java.lang.String[]); Code: 0: iconst_1 1: istore_1 2: iload_1 3: ifeq 8 6: iconst_0 7: istore_1 8: return 

对于第二个代码 ,生成的字节码较短,因为缺少比较:

  public static void main(java.lang.String[]); Code: 0: iconst_1 1: istore_1 2: iconst_0 3: istore_1 4: return 

虚拟机在第一个示例中执行8个命令比在第二个示例中执行8个命令需要更多时间。 虽然这种差异不应该高,但第二代码更清楚。

将代码放在一个简单的main方法中并编译该类。 然后运行命令提示符并切换到java/bin目录。 要反汇编类,请调用javap -c path/to/YourClass.class >> path/to/bytecode.txt 。 bytecode.txt将包含您的类的java字节码。

“速度差异”(如果有的话)将完全取决于JVM。 任何体面的编译器都应该能够优化测试,此时两者是相同的。

例外:如果var声明为volatile则条件版本将始终较慢。

在任何情况下,如果性能至关重要,最好的选择是在预期条件下(机器,系统,JVM,典型负载等)进行测量。

我在这个游戏上玩的很晚,但我写了这个测试类来回答类似的问题。

 package SpeedTests; import java.text.NumberFormat; import java.util.Locale; public class BooleanSpeedTest { public static void main(String[] args) { boolean BoolTest = true; long LongLoop = 100000; long TrueLoopCount = 0; long FalseLoopCount = 0; long TimeTotal = 0; long startTime; long endTime; for(int intLoopA = 1; intLoopA < 6; intLoopA++) { LongLoop = LongLoop * 10; TimeTotal = 0; System.out.println(""); System.out.print( NumberFormat.getNumberInstance(Locale.US).format(LongLoop) + " - "); for(int intLoopM = 0; intLoopM < 20; intLoopM++) { TrueLoopCount = 0; FalseLoopCount = 0; startTime = System.currentTimeMillis(); for(long LoopCount = 0; LoopCount < LongLoop; LoopCount++) { if(!BoolTest) { TrueLoopCount++; } else FalseLoopCount++; } endTime = System.currentTimeMillis(); System.out.print( (endTime - startTime) + "ms "); TimeTotal += ((endTime - startTime) ); } System.out.print(" AVG: " + (TimeTotal/20)); } } } 

我的结果:平均时间/十亿(ms)注意每循环时间

 if(BoolTest) 443 When False 0.00000443 if(BoolTest) 443 When True if(BoolTest == false) 443 When False if(BoolTest == false) 442 When True if(!BoolTest) 438 When False if(!BoolTest) 441 When True (BoolTest ? Var++ : Var--) 435 When True (BoolTest ? Var++ : Var--) 435 When False