行为相同的条件检查的表现 [英] Performance of behaviorally identical conditional checks

查看:108
本文介绍了行为相同的条件检查的表现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我回答了这个问题和注意到在为它运行代码时引起我兴趣的东西。部分问题是关于各种类型的相同条件检查的表现,例如:

I answered this question and noticed something that intrigued me while running the code for it. Part of the question was about the performance of various styles of identical conditional checks, for example:

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

对比

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

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

I wrote a program that times how long a certain number of iterations takes to execute, and the results are what I don't understand.

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

Here's the output of my program on my machine (Win 8.1 64-bit, javac 1.8.0_11 (Oracle), java 1.0.0_11 (Java SE, Oracle). I've ran each trial multiple times and they yield repeatable results.

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

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

Why do runs of all methods takes longer (in the case of chainIf, almost 300% more time) when the values they are checking allow them all to short curcuit?

我已经使用调试器完成了所有这些操作,并且它们实际上是短暂的(如我所料)。我检查了字节码和 chainedIf() multipleIf()完全相同。我很难过和好奇。

I've stepped through them all with the debugger, and they do infact short curcuit (as I'd expect). I've examined the bytecode and chainedIf() and multipleIf() are exactly identical. I'm stumped and curious.

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

I'm not sure if there's some flaw in the way I'm performing my measurement, so I've included my program below.

节目来源

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; 
    }
}


推荐答案


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

Why do runs of all methods takes longer (in the case of chainIf, almost 300% more time) when the values they are checking allow them all to short curcuit?

因为您的基准测试有问题。请阅读类似问题的答案:

一些运行/ JIT错误后Java循环变慢了?

Because your benchmark is faulty. Please read the answer to a similar question:
Java loop gets slower after some runs / JIT's fault?

这篇关于行为相同的条件检查的表现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆