在java中检查布尔值比设置布尔值快吗?
这: 与此相比:在java中检查布尔值比设置布尔值快吗?,java,performance,Java,Performance,这: 与此相比: if (var) { var = false; } 是否存在速度差异?第一个代码包含一个比较,因此您的编译器可能会生成如下所示的java字节码: var = false; 对于第二个代码生成的字节码较短,因为缺少比较: public static void main(java.lang.String[]); Code: 0: iconst_1 1: istore_1 2: iload_1
if (var) {
var = false;
}
是否存在速度差异?第一个代码包含一个比较,因此您的编译器可能会生成如下所示的java字节码:
var = false;
对于第二个代码生成的字节码较短,因为缺少比较:
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
在第一个示例中,虚拟机执行8个命令所需的时间比在第二个示例中执行4个命令所需的时间多。虽然这个差别不应该太大,但第二个代码更清楚
将代码放在一个简单的main方法中并编译该类。然后运行命令提示符并切换到
java/bin
目录。要反汇编类,请调用javap-cpath/To/YourClass.class>>path/To/bytecode.txt
。bytecode.txt将包含您的类的java字节码。有几件事需要考虑,对实际性能的最终影响是您需要根据您的用例来衡量的。我认为这是一种你经常发现的方法:
这是一个优化的人,例子可以在JDK(Irc)中找到,我想你有理由考虑它。
< p>“速度差”,如果有的话,将完全取决于JVM。任何优秀的编译器都应该能够优化测试,在这一点上,两者是相同的 例外情况:如果var
被声明为volatile
,条件版本将始终较慢
在任何情况下,如果性能至关重要,最好的选择是在预期条件下(机器、系统、JVM、典型负载等)对其进行测量。关于这一点,我在游戏中迟到了,但我编写这个测试类是为了回答一个类似的问题
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: iconst_0
3: istore_1
4: return
这是另一个廉价的“基准”(几乎不配使用这个术语)。对我来说,猴子扳手基准的结果对于OP的问题并没有明确地说出来,所以我想我也应该把它放在这里
结果(在这些条件下,并且仅在很少的测试中):在编写局部布尔值之前检查它比在没有必要的情况下经常编写要好
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
publicstaticvoidmain(字符串[]args){
最终随机数r=新随机数(0);
布尔b=假;
布尔决策;
长启动时间;
长时间;
startTime=System.currentTimeMillis();
对于(长i=0;i<100000000;i++){
decision=r.nextDouble()>0.1;//在大多数情况下都是正确的。
如果(决定){
//如果(!b){
b=正确;
// }
}
}
endTime=System.currentTimeMillis();
System.err.println(endTime-startTime);
系统错误println(b);
系统出口(0);
}
直截了当地写道(ms):
18139
18140
18196
(18220)
(18181)
----------
平均值3:18158.333333
平均值5:18175.2
写前检查(ms):
18097
18109
18115
(18129)
(18133)
----------
平均值3:18107
平均值5:18116.6
通过检查,仅获取该百分比(3个样本):99.7173015144561725621844882974
通过检查,它仅获取此%(5个样本):99.677582640080949480170782164708
通过检查,大约需要99.7%的书写时间。如果写操作在其他情况下不必要地发生,则通常。在这个蹩脚的“基准测试”中,也就是说。但复杂性增加了。速度是微观的,与此无关。如果需要将
var
设置为false
,请进行设置。如果您之前需要检查它当前是否为true
,那么请先检查。添加可能触发错误分支预测的分支是一件非常可怕的事情。通常更有效的方法是做更多的工作来避免分支(1/0的乘法等),因为这会变得多么糟糕。相关的,@ZouZou(以及Mena)你的评论是在说教,而不是在告知。这不是OP是否应该关心的问题。也不是哪种方法更容易阅读。字节码不是性能的好指标,除非你计划把大部分时间花在解释器上。你错了。易失性读取比写入便宜得多。这是一个经过测试的针对易失性字段写入的优化。@NitsanWakart也许我不清楚。如果var
被声明为volatile
,那么OP的语句If(var){var=false;}
总是比var=false慢因为编译器不会优化读取var
;因此产生了读和写的成本,而不仅仅是写。我没有说明volatile读取和写入之间的性能差异。这种说法“将始终较慢”是不正确的。只有当var为true时才是正确的,它假设OP不与我们共享代码。当var已经为false时,条件写入总是比IME更快(因为volatile写入不会发生,而且比读取要昂贵得多)。感谢您的澄清,我现在了解到您
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
public static void main(String[] args) {
final Random r = new Random(0);
boolean b = false;
boolean decision;
long startTime;
long endTime;
startTime = System.currentTimeMillis();
for (long i = 0; i < 1000000000; i++) {
decision = r.nextDouble() > 0.1; // Will be true MOST of the time.
if (decision) {
// if (!b) {
b = true;
// }
}
}
endTime = System.currentTimeMillis();
System.err.println(endTime - startTime);
System.err.println(b);
System.exit(0);
}
With bluntly writing (ms):
18139
18140
18196
(18220)
(18181)
----------
Average of 3: 18158.333333333333333333333333333
Average of 5: 18175.2
With checking before writing (ms):
18097
18109
18115
(18129)
(18133)
----------
Average of 3: 18107
Average of 5: 18116.6
With checking, it only takes this % (3 samples): 99.71730151445617255621844882974
With checking, it only takes this % (5 samples): 99.677582640080989480170782164708