Performance 哪种情况在技术上更有效,i>;=0或i>-1.
这种用法在编写循环时很常见Performance 哪种情况在技术上更有效,i>;=0或i>-1.,performance,comparison,cpu-usage,conditional-statements,Performance,Comparison,Cpu Usage,Conditional Statements,这种用法在编写循环时很常见 我想知道I>=0是否需要更多的CPU周期,因为与I>-1相比,它有两个条件大于或等于。一个比另一个好,如果是,为什么?这是不正确的。JIT将把这两个测试作为一条机器语言指令来实现 CPU时钟周期的数量不是由比较到零或-1的数量决定的,因为CPU应该进行一次比较,并设置标志来指示比较的结果是或= 这些指令中的一条可能在某些处理器上更有效,但这种微优化几乎总是不值得做的。(JIT或javac也有可能为两个测试实际生成相同的指令。)相反,带零的比较(包括非严格比较)减少一条
我想知道
I>=0
是否需要更多的CPU周期,因为与I>-1
相比,它有两个条件大于或等于
。一个比另一个好,如果是,为什么?这是不正确的。JIT将把这两个测试作为一条机器语言指令来实现
CPU时钟周期的数量不是由比较到零或-1的数量决定的,因为CPU应该进行一次比较,并设置标志来指示比较的结果是或=
这些指令中的一条可能在某些处理器上更有效,但这种微优化几乎总是不值得做的。(JIT或javac也有可能为两个测试实际生成相同的指令。)相反,带零的比较(包括非严格比较)减少一条CPU指令。x86体系结构支持在任何算术或加载操作之后进行条件跳转。它反映在Java字节码指令集中,有一组指令用于比较堆栈顶部的值并跳转:
ifeq
/ifgt
/ifge
/iflt
/ifle
/ifne
。(见附件)。与-1
相比,需要额外的iconst_m1
操作(将-1
常量加载到堆栈上)
这是两个具有不同分区的循环:
@GenerateMicroBenchmark
public int loopZeroCond() {
int s = 0;
for (int i = 1000; i >= 0; i--) {
s += i;
}
return s;
}
@GenerateMicroBenchmark
public int loopM1Cond() {
int s = 0;
for (int i = 1000; i > -1; i--) {
s += i;
}
return s;
}
第二个版本长一个字节:
public int loopZeroCond();
Code:
0: iconst_0
1: istore_1
2: sipush 1000
5: istore_2
6: iload_2
7: iflt 20 //
10: iload_1
11: iload_2
12: iadd
13: istore_1
14: iinc 2, -1
17: goto 6
20: iload_1
21: ireturn
public int loopM1Cond();
Code:
0: iconst_0
1: istore_1
2: sipush 1000
5: istore_2
6: iload_2
7: iconst_m1 //
8: if_icmple 21 //
11: iload_1
12: iload_2
13: iadd
14: istore_1
15: iinc 2, -1
18: goto 6
21: iload_1
22: ireturn
在我的机器上它的性能稍微好一点(让我吃惊的是,我希望JIT能将这些循环编译成相同的程序集。)
С结论
在合理的情况下与零进行比较。我建议你永远不会注意到区别,所以做些可读性更好的事情。@SaadAbdullah你为什么这么认为?@SaadAbdullah正数到负数的转换?想得太多了。Java在内部处理这个问题。两种形式的表现应该相同。这真的是一个4票赞成的问题吗?这个问题不是基于意见的@萨达杜拉是对的。从性能角度来看,使用0进行比较通常更可取,因为与非零比较相比,它们通常可以保存一条x86指令,因为
ZF
,CF
,etc标志设置在每个算术或加载指令之后。@ElliottFrisch您是指Oracle javac吗?(Eclipse和GCC都有自己的Java编译器。)哪个版本?你测试过了吗?
Benchmark Mode Thr Mean Mean error Units
t.LoopCond.loopM1Cond avgt 1 0,319 0,004 usec/op
t.LoopCond.loopZeroCond avgt 1 0,302 0,004 usec/op