【问题标题】:Which condition is technically more efficient, i >= 0 or i > -1?哪个条件在技术上更有效,i >= 0 还是 i > -1?
【发布时间】:2013-11-13 06:27:10
【问题描述】:

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

我想知道i >=0 是否需要更多的 CPU 周期,因为与i > -1 相比,greater than OR equal to 有两个条件。是否已知一个比另一个更好,如果是,为什么?

【问题讨论】:

  • 我建议你永远不会注意到差异,所以做更具可读性的东西。
  • @SaadAbdullah 你为什么这么认为?
  • @SaadAbdullah 将正数转换为负数?想太多。 Java 在内部处理这个问题。两种形式的性能应该相同。
  • 这真的是一个 4 票赞成的问题吗?
  • 这个问题不是基于意见的。 @SaadAbdullah 是对的。从性能的角度来看,与 0 的比较通常更可取,因为与非零比较相比,它们通常会节省一条 x86 指令,因为在每个算术或加载指令之后都会设置 ZFCF 等标志。

标签: performance comparison cpu-usage conditional-statements


【解决方案1】:

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

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

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

【讨论】:

  • @ElliottFrisch 你的意思是Oracle javac? (Eclipse 有自己的 Java 编译器,GCC 也有。)哪个版本?你测试过吗?
【解决方案2】:

相反,与零的比较(包括非严格)减少了一条 CPU 指令。 x86 架构支持任何算术或加载操作后的条件跳转。体现在Java字节码指令集中,有一组指令比较栈顶的值并跳转:ifeq/ifgt/ifge/iflt/ifle/@987654327 @。 (见the full list)。与-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 将这些循环编译成相同的程序集。)

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

结论

在合理的情况下与零比较

【讨论】:

    猜你喜欢
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-24
    • 1970-01-01
    • 2015-08-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多