哪个更快:
if(this.foo != 1234)
this.foo = 1234;
或
this.foo = 1234;
是写得足够高的惩罚,人们应该在写入之前检查值,还是写入更快?
不会有分支导致可能的错误预测和搞砸cpu pipleine?但是这个字段是不稳定的,写入的成本比读取成本高?
是的,很容易说这些操作本身是“免费的”或基准测试,但这不是答案。
答案 0 :(得分:2)
有一个很好的例子说明了最近talk by Sergey Kuksenko about hardware counters(幻灯片45-49)中的这种困境,相同代码的正确答案取决于数据大小!这个想法是"比较和设置"方法导致更多的分支未命中和负载,但更少的存储和L1存储未命中。差异是微妙的,我甚至无法理解为什么一个因素超重对小数据大小不同,但在大数据大小上变得不那么重要。
所以,测量,不要猜测。
答案 1 :(得分:1)
这些操作都是免费的:它们几乎没有时间!
现在,如果此代码处于循环中,您绝对应该支持第二个选项,因为它将最小化分支误预测。
否则,重要的是使代码更具可读性的原因。在我看来,第二种选择更清楚。
同样如评论中所提到的,分配是一种使其线程安全的原子操作。第二种选择的另一个优点。
答案 2 :(得分:1)
他们不是免费的。他们花费时间和空间。由于分支预测(现在的孩子和他们现代的CPU),在紧密循环中分支实际上可能非常昂贵。请参阅Mysticial's回答。
但大多数情况下都没有意义。要么只是设置它应该是什么,要么当它不是你所期望的时候扔掉 你让我读的任何代码最好有充分的理由存在。
我认为你要做的是表达你期望它的价值,并断言它应该是那样。如果没有上下文,我不能告诉你是否应该在你的期望被违反时扔掉,或者只是分配断言它应该是什么。但是,让您的期望清晰并以某种方式强制执行它们肯定值得一些CPU周期。我宁愿你比快速给我垃圾和垃圾更慢一点。
答案 3 :(得分:1)
我认为这实际上是一个普遍的问题,而不是与java相关的问题,因为此操作的级别较低(CPU,而不是JVM级别)。
首先,让我们看看选择是什么。另一方面,我们reading from memory + comparison + (optionally) writing to memory
,writing to memory
。
内存访问比注册表操作(对已加载到CPU的数据操作)要昂贵得多。因此,选择read + (sometimes) write
vs write
。
什么更贵,读或写?简短的回答 - 写。答案很长 - 写,但差异可能很小,取决于系统缓存策略。用几句话来解释并不容易,你可以在这本美丽的书中获得更多关于缓存的知识"操作系统"作者:William Stallings。
我认为在实践中你可以忽略读写操作之间的区别,只是在没有测试的情况下编写。那是因为(返回Java)你的对象及其所有字段将暂时存在于缓存中。
要考虑的另一件事是分支预测 - 其他人已经提到过,这也是没有测试就能写出价值的原因。
答案 4 :(得分:0)
这取决于你真正感兴趣的东西。
如果这是一个普通的老式程序,不仅第一个方案的fetch / compare / branch需要额外的时间,而且还有额外的代码和复杂性,即使第一个方案确实节省了极少的时间(而不是花费时间)不值得这样做。
但是,有些情况会有所不同。在具有多个处理器的强烈多线程环境中,修改共享存储可能是昂贵的,因为对该存储的更改需要传播到其他处理器。在这样的环境中,花一些额外的指令来避免“弄脏”缓存是非常值得的。