漫画:奇怪,为什么在Java中 2*(i*i) 比 2*i*i 快?

640?wx_fmt=png

640?wx_fmt=png

既然我设计的两只小萌宠出场了,也该它们的粑粑出场了,今天这篇文章,我们通过一个故事来深入聊聊 Java 编译背后的秘密。


640?wx_fmt=png

640?wx_fmt=png

640?wx_fmt=png

640?wx_fmt=png

640?wx_fmt=png


东哥说这段代码来自于 Stackoverflow,真正去逛这个网站的同学还是很少),如下。



代码很简单吧,它的执行时间大概在 0.60s ~ 0.65s。但是如果你把 2*i*i 替换成 2*(i*i),执行时间大概在 0.50s ~ 0.55s。


对这段程序的两个版本分别执行 15 次,得到的结果如下。


640?wx_fmt=png


我们可以看出 2*(i*i) 比 2*i*i 快 。


640?wx_fmt=png

我们来分别查看它的字节码,这里东哥给我推荐了一款好用的 IDEA 插件,叫做 jclasslib bytecode viewer。


 2*i*i 的字节码如下。


640?wx_fmt=png


2*(i*i) 的字节码如下。


640?wx_fmt=png


我们可以发现除了字节码顺序不同外,没有其它异常,下一步该怎么办呢?


640?wx_fmt=png



这里东哥给我推荐一款开源的工具,叫做 jitwatch,它可以查看查看分析HotSpot JIT compiler 生成的汇编代码,关于它的安装方法可以通过谷歌查阅。


查看是否安装成功?可以用下面的命令。


640?wx_fmt=png


如何查看汇编代码?


运行时,添加参数 -XX:+PrintAssembly。


好了,那我们来分别看看它们的汇编代码,由于汇编代码很多,我这里就不贴出来了,各位同学可以去运行分析一下。


我这里就说一下结论,通过对比分析,我们会发现,2*i*i 进行了大量的堆栈操作,因此,需要保存大量的中间结果;而 2*(i*i) 只有少量的堆栈操作。


显而易见,2*(i*i) 比 2*i*i 快是由于 JIT 优化的结果。


640?wx_fmt=png

-END-

纯洁的微笑

一个有故事的程序员


640?wx_fmt=jpeg

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值