【发布时间】:2016-10-19 20:37:06
【问题描述】:
免责声明:我在逆向工程字节码方面没有太多经验,所以如果可以“轻松”回答我的问题,请不要对我太苛刻。
在现代处理器上,如果预测失败,分支可能会非常昂贵(请参阅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-check 比可能预测错误的分支要便宜得多?
(很明显,如果不冒NullPointerException 的风险,我无法摆脱第二个&&。)
现在,在我被诸如“过早的优化是万恶之源!”之类的陈述撕成碎片之前,请记住这是在一般编码习惯之间的选择(始终使用短路与从不使用短路) -电路,除非需要),这将影响我的代码几乎所有,所以确保我在这里使用正确的习惯绝对值得花一些时间思考。
【问题讨论】:
-
1) 过早优化是万恶之源!" 2) 使用
&&是一个非常好的习惯。 -
1) 是的,我确实知道 Java 是如何实现短路的,并且 2) 我真诚地相信,在一种尽一切可能抽象的语言中,担心极低级别、高度特定于 CPU 的行为远离底层平台是......成为慈善......“被误导”。无意义。浪费时间。几乎可以肯定会因情况而异。如果有疑问,我鼓励您尝试一些基准测试并发布结果:)
-
您现在已经花了多少时间研究和讨论这个问题,而这很可能对您的代码没有明显的影响?也许可以衡量,但很明显? 过早优化的概念是把你非常宝贵的时间花在重要的事情上,所以把时间浪费在很可能不会重要的事情上,你就会有那么多在截止日期之前花更少的时间在真正重要的代码上。当然,如果您有空闲时间,您可以尝试优化,但您如何知道您的尝试有助于而不是损害性能??
-
这真的取决于分支是否可能被正确预测,这与合成基准完全不同。您可以尝试衡量一个至少稍微现实的版本,在该版本中,您将两个成本相同的操作放在 && 上,其中一个为假,另一个为变量。交换一下,看看你是否得到了可衡量的效果。但同样,在 Java 中摆弄这个很可能是徒劳的。
-
字节码不会将 1-1 映射到 CPU 指令。相同的字节码可以解释运行,并以不同程度的优化进行 JIT,即在其生命周期内运行不同的 CPU 指令。因此,所有“你不能轻易地从 Java 代码中推断出这一点”的谈话。
标签: java performance short-circuiting