0

这种用法在编写循环时很常见。

我想知道是否i >=0需要更多的 CPU 周期,因为greater than OR equal toi > -1. 是否已知一个比另一个更好,如果是,为什么?

4

2 回答 2

8

这是不正确的。JIT 将把这两个测试作为一个单一的机器语言指令来实现。

并且CPU时钟周期数不是由比较次数决定为零还是-1,因为CPU应该做一次比较,并设置标志来指示比较的结果是<、>还是=。

在某些处理器上,其中一条指令可能会更有效,但这种微优化几乎总是不值得做的。(也有可能 JIT - 或 javac - 实际上会为两个测试生成相同的指令。)

于 2013-11-13T06:30:15.100 回答
3

相反,与零的比较(包括非严格)减少了一条 CPU 指令。x86 体系结构支持任何算术或加载操作后的条件跳转。体现在Java字节码指令集中,有一组指令比较栈顶的值并跳转:ifeq///// 。(查看完整列表)。比较需要额外的操作(将常量加载到堆栈上)。ifgtifgeifltifleifne-1iconst_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 将这些循环编译成相同的程序集。)

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

结论

在合理的情况下与零进行比较。

于 2013-11-26T20:49:01.457 回答