为什么处理有序数组要比非有序数组快?
这个问题在那篇博客开头就被提出来了,很明显这也是和分支预测有关系,既然看到了索性就再分析一波,大伙可以在脑海里先回答一下这个问题,毕竟咱们都知道答案了,看看思路清晰不。
就是下面这段代码,数组排序了之后循环的更快。
然后各路大神就蹦出来了,我们来看一下首赞的大佬怎么说的。
一开口就是,直击要害。
You are a victim of branch prediction fail.
紧接着就上图了,一看就是老司机。
他说让我们回到 19世纪,一个无法远距离交流且无线电还未普及的时候,如果是你这个铁路交叉口的扳道工,当火车快来的时候,你如何得知该扳哪一边?
火车停车再重启的消耗是很大的,每次到分叉口都停车,然后你问他,哥们去哪啊,然后扳了道,再重启就很耗时,怎么办?猜!
猜对了火车就不用停,继续开。猜错了就停车然后倒车然后换道再开。
所以就看猜的准不准了!搏一搏单车变摩托。
然后大佬又指出了关键代码对应的汇编代码,也就是跳转指令了,这对应的就是火车的岔口,该选条路了。
后面我就不分析了,大伙儿应该都知道了,排完序的数组执行到值大于 128 的之后肯定全部大于128了,所以每次分支预测的结果都是对了!所以执行的效率很高。
而没排序的数组是乱序的,所以很多时候都会预测错误,而预测错误就得指令流水线排空啊,然后再来一遍,这速度当然就慢了。
所以大佬说这个题主你是分支预测错误的受害者。
最终大佬给出的修改方案是咱不用 if 了,惹不起咱还躲不起嘛?直接利用位运算来实现这个功能,具体我就不分析了,给大家看下大佬的建议修改方案。
最后
这篇文章就差不多了,今天就是从 Dubbo 的一段代码开始了探险之旅,分析了波 if 和 switch,从测试结果来看 Dubbo 的这次优化还不够彻底,应该全部改成 if else 结构。
而 swtich 从字节码上看是优于 if 的,但是从测试结果来看在分支很多的情况下能显示出优势,一般情况下还是打不过 if 。
然后也知晓了什么叫指令流水线,这其实就是结合实际了,流水线才够快呀,然后分支预测预执行也是一个提高效率的方法,当然得猜的对,不然分支预测错误的副作用还是无法忽略的,所以对分支预测器的要求也是很高的。
JMH 的测试代码我也打个包,想自己跑的同学后台输入「分支预测」即可获取,如果觉得这篇文章不错点个在看哟,如果有纰漏请赶紧联系鞭挞我。
巨人的肩膀
Spectre :www.freebuf.com/vuls/160161…
Dubbo 博客 :dubbo.apache.org/zh-cn/blog/…
stackoverflow.com/questions/1…