行为相同的条件检查的表现

时间:2014-08-11 04:40:37

标签: java performance jit

我回答this question并注意到在运行代码时引起我兴趣的东西。部分问题是关于各种风格的相同条件检查的表现,例如:

if (x > 0) { 
    if (y > 0) { 
        if (z > 0) { 
            if (complexCondition()) { 
                 noOp();
            }
        }
    }
}

if (x > 0 && y > 0 && z > 0 && complexCondition()) { 
     noOp();
}

我编写了一个程序,计算执行一定次数的迭代需要多长时间,结果是我不明白的结果。

这是我的程序在我的机器上的输出(Win 8.1 64位,javac 1.8.0_11(Oracle),java 1.0.0_11(Java SE,Oracle)。我已经多次运行每个试验并且它们可重复结果。

x = 9, y = 2, z = 8, countTrials = 1, iterationsPerTrial = 2736000
Method        Average Runtime(ns)
guardIf()     5746173
multipleIf()  4868180
chainedIf()   9316172

x = 9, y = 2, z = 8, countTrials = 100, iterationsPerTrial = 2736000
guardIf()     1642750
multipleIf()  1121897
chainedIf()   1739522

x = -1, y = 2, z = 8, countTrials = 1, iterationsPerTrial = 2736000 // I expect shorter results with x = -1, because they all short curcuit
guardIf()     9245313
multipleIf()  8728608
chainedIf()   11718332

x = -1, y = 2, z = 8, countTrials = 100, iterationsPerTrial = 2736000 
guardIf()     1754279
multipleIf()  1611278
chainedIf()   4947295

毫秒测量(用org.apache.commons.lang3.time.StopWatch实现)

x = 9, y = 2, z = 8, countTrials = 1, iterationsPerTrial = Integer.MAX_VALUE
Method        Average Runtime(ms)
guardIf()     1664
multipleIf()  1095
chainedIf()   1654

x = -1, y = 2, z = 8, countTrials = 1, iterationsPerTrial = Integer.MAX_VALUE
Method        Average Runtime(ms)
guardIf()     4886
multipleIf()  4926
chainedIf()   4862

x = 9, y = 2, z = 8, countTrials = 10, iterationsPerTrial = Integer.MAX_VALUE
Method        Average Runtime(ms)
guardIf()     1673
multipleIf()  1108
chainedIf()   1682

x = -1, y = 2, z = 8, countTrials = 10, iterationsPerTrial = Integer.MAX_VALUE
Method        Average Runtime(ms)
guardIf()     4364
multipleIf()  4363
chainedIf()   4877

为什么所有方法的运行需要更长时间(在chainIf的情况下,时间几乎多300%),当他们检查的值允许它们全部缩短时?

我已经使用调试器完成了所有这些操作,并且它们实际上做了一些简短的工作(正如我所期待的那样)。我检查了字节码,chainedIf()multipleIf()完全相同。我很难过和好奇。

我不确定我的测量方式是否有一些缺陷,所以我在下面列出了我的程序。

计划来源

class TrialResult {
    public long GuardIf = 0; 
    public long MultipleIf = 0; 
    public long ChainedIf = 0; 

    public TrialResult(long guardIf, long multipleIf, long chainedIf) { 
        this.GuardIf = guardIf; 
        this.MultipleIf = multipleIf; 
        this.ChainedIf = chainedIf; 
    }
}

public class Program {

    private int x; 
    private int y; 
    private int z; 

    public static void main(String[] args) { 
        Program program = new Program(); 
        List<TrialResult> trials = new ArrayList<TrialResult>(); 
        int countTrials = 1; 

        for (int j = 0; j < countTrials; j++) {     
            long t0 = 0, t1 = 0; 

            t0 = System.nanoTime();
            for (long i = 0; i < 2073600; i++) { 
                program.chainedIf();
            }
            t1 = System.nanoTime();
            long chainIf = t1 - t0;

            t0 = System.nanoTime();
            for (long i = 0; i < 2073600; i++) { 
                program.multipleIf();
            }

            t1 = System.nanoTime();
            long multipleIf = t1 - t0;

            t0 = System.nanoTime();
            for (long i = 0; i < 2073600; i++) { 
                program.guardIf();
            }
            t1 = System.nanoTime();
            long guardIf = t1 - t0;
            System.out.printf("Trial %d completed\r\n", j+1);

            trials.add(new TrialResult(guardIf, multipleIf, chainIf)); 
        }

        long chainIf = 0, multipleIf = 0, guardIf = 0; 
        for (TrialResult r : trials) { 
            chainIf += r.ChainedIf; 
            multipleIf += r.MultipleIf; 
            guardIf += r.GuardIf; 
        }
        System.out.printf("%d, %d, %d", guardIf / trials.size(), multipleIf / trials.size(), chainIf / trials.size()); 
    }

    private Program() {
        x = 9; 
        y = 2; 
        z = 8; 
    }

    private void chainedIf() { 
        if (x > 0) { 
            if (y > 0) { 
                if (z > 0) { 
                    if (complexCondition()) { 
                         noOp();
                    }
                }
            }
        }
    }

    private void multipleIf() { 
        if (x > 0 && y > 0 && z > 0 && complexCondition()) { 
             noOp();
        }
    }

    public void guardIf() { 
        if (x <= -1) { 
            return; 
        }

        if (y <= -1) { 
            return; 
        }

        if (z <= -1) { 
            return; 
        }

        if (!complexCondition()) { 
            return; 
        }

         noOp();
    }

    private boolean complexCondition() { 
        return (x > 0 && 
            y < x && 
            y + z > x
        );      
    }

    private void noOp() { 
        return; 
    }
}

1 个答案:

答案 0 :(得分:0)

  

为什么所有方法的运行需要更长时间(在chainIf的情况下,几乎多300%的时间),当它们检查的值允许它们全部缩短curcuit时?

因为您的基准测试有问题。请阅读类似问题的答案:
Java loop gets slower after some runs / JIT's fault?