免责声明:我在逆向工程字节码方面没有太多经验,所以如果可以轻松地对我进行操作,请不要过于苛刻。回答我的问题。
在现代处理器上,如果预测失败,分支可能会非常昂贵(参见Why is it faster to process a sorted array than an unsorted array?)。
让我们说我在Java中有一些像这样的短路评估:
if (condition && (list!=null) && (list.size()>0)) /* Do something */ ;
这基本上相当于一堆像这样的分支:
if (condition) {
if (list!=null) {
if (list.size()>0) {
// Do something
}
}
}
或者Java是否有其他方法可以更巧妙地进行短路?
换句话说,最好通过重写这样的行来避免至少一个分支:
if ((condition & (list!=null)) && (list.size()>0)) /* Do something */ ;
因为简单的list!=null
- 检查比可能预测错误的分支要便宜得多吗?
(显然,我无法摆脱第二个&&
而不会冒NullPointerException
的风险。)
现在,在我用#34之类的陈述撕成碎片之前,过早的优化是所有邪恶的根源!",请记住,这是一般编码习惯之间的选择(总是使用短 - 电路与从不使用短路,除非需要),这将影响我的代码的所有,所以确保我在这里使用正确的习惯绝对值得花些时间考虑。
答案 0 :(得分:1)
没有here提及任何类型的分支。这仅仅是表达式评估,&&
语句中的if
与表达式中的&&
没有区别。你能用下面的代码问同样的问题吗?
boolean isValid = condition && (list!=null) && (list.size()>0);
if (isValid) {
...
}
这基本上就是这样,表达式被评估,然后发生分支。
答案 1 :(得分:1)
我做了一个简单的测试
int sum = 0;
Random rnd = new Random(1);
int[] a = new int[1000];
int[] b = new int[1000];
for (int i = 0; i < 1000; ++i)
{
a[i] = rnd.nextInt(100);
b[i] = rnd.nextInt(100);
}
long started = System.nanoTime();
for (int i = 0; i < 1000000; ++i)
{
for (int j = 0; j < 1000; ++j)
{
if (a[j] < 50 && b[j] < 5)// change "&& b[j] < 5"
{
sum++;
}
}
}
long ended = System.nanoTime();
System.out.println((ended - started)/1000000 + " " + sum);
结果非常随机:
&& &
b[j] < 5 1450 1360
b[j] < 50 1330 1610
b[j] < 500 1310 1450
j < 50 2200 920
j < 500 1410 1730
j < 5000 1180 1040
j < i 1180 2050
i < j 2290 1450
这些是来自更多运行的最低值,我确保它们是可重复的。实际时间因运行而异。作为一个经验法则,我会避免过于花哨,坚持&amp;&amp; amp;希望优化&#34;在那里&#34;尽全力。有关于optimizations
的精彩视频修改强>
正如Dici指出的那样,应该完成JVM的热身。似乎函数的第一次和第二次调用与其他函数不同。当增加循环次数时,规则也始终适用。所以我重新测试了那个......又弄得一团糟。平均速度提高约2倍,但再次变得混乱。并且优化更加不稳定,通常没有一个,但两个典型的时间值甚至50%不同。我看了JMH,很好的框架。我可以测量一下&amp;比&amp;&amp;更快如果我真的尝试过(在不同的系统,不同的硬件等等,很多工作)。但这不是问题。问题是,如果我更换&amp;&amp; for&amp;在我的程序中,我可以期待它更快还是更慢?答案是 - 你不能指望任何事情,你必须衡量它。
<强> EDIT2 强>
在这种情况下,我认为这是浪费时间,但为了维护我的可信度,我测量了标准偏差(又称一个西格玛)。在几次运行中,值表现得非常好,并且它们在数千次运行中表现良好,这并不令人意外(我没有在JVM热身后显示结果,因为它们表现不佳并且统计数据将是不可避免的)。有趣的是,所有结果都比我预测的结果快7%左右,对于大多数值来说,这超过了5西格玛。从几次尝试看来,网页浏览器标签似乎影响整个系统的速度,不,我不会做统计数据来确认我的观察。
&& &
b[j] < 5 1333(14) 1265(25)
b[j] < 50 1231(11) 1514(13)
b[j] < 500 1223(9) 1360(13)
j < 50 2069(74) 842(11)
j < 500 1294(12) 1631(17)
j < 5000 1089(9) 957(8)
j < i 1086(8) 1907(23)
i < j 2164(16) 1357(14)