这种用法在编写循环时很常见。
我想知道i >=0
是否需要更多的CPU周期,因为它与greater than OR equal to
相比有两个条件i > -1
。是否已知一个比另一个好,如果是,为什么?
答案 0 :(得分:7)
这不正确。 JIT将两个测试都作为单一机器语言指令实现。
CPU时钟周期数不是由零或-1的比较数决定的,因为CPU应进行一次比较并设置标志以指示比较结果是否为<,>。或=。
这些指令之一可能在某些处理器上更有效,但这种微优化几乎总是不值得做。 (也有可能JIT - 或者javac - 实际上会为两个测试生成相同的指令。)
答案 1 :(得分:3)
相反,带零的比较(包括非严格)会减少一条CPU指令。 x86架构支持任何算术或加载操作后的条件跳转。它反映在Java字节码指令集中,有一组指令用于比较堆栈顶部的值和跳转:ifeq
/ ifgt
/ ifge
/ {{1} } / iflt
/ ifle
。 (见the full list)。与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;
}
我的机器性能略高一些(令我惊讶的是。我希望JIT将这些循环编译成相同的程序集。)
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
与零比较。