为什么这个GoLang解决方案比等效的Java解决方案更快?
最近在工作中,我们正在玩IBM提出的以下测验问题 https://www.research.ibm.com/haifa/ponderthis/challenges/May2015.html
经过一番努力,我和我的一位同事已经找到了两种解决方案,一种是在GoLang https://gist.github.com/walesey/e2427c28a859c4f7bc920c9af2858492#file-main-go-L57 中,另一种是在Java中,https://gist.github.com/boyter/42df7f203c0932e37980f7974c017ec5#file-puzzle-java-L63 性能关键方法,即Java中的playGames和GoLang中的game(两者都在上面链接)。
Go程序几乎是Java程序的字面副本,但它的运行时间约为6秒,而Java程序的运行时间约为26秒(在我的本地计算机上)。类似的数字在其他几台机器上复制,Go程序的速度提高了约5倍。
Go程序是使用1.7.5编译的,Java使用版本1.8.0_65编译的,两者都运行在macOS Sierra 10.12.3上,在2013年末的retina Macbook Pro上,配备2.6GHz i5 CPU。
为什么Go程序比Java程序快5倍,而大多数基准测试表明Java应该使用相同的运行时?它只是循环中的基本数学,因此它们似乎应该同时运行。对于JVM的开始时间,我可以理解一秒钟左右,但这似乎不对。
这两个程序几乎使用相同的循环。将为每个起始金额创建并迭代所有可能的游戏结果排列。似乎对于主循环中任意数量的循环操作,Go 都在 Java 周围运行环。
我知道这是一个“微”基准测试,但我想知道为什么Go代码的性能远远超过Java代码。只是 Go for simple 循环/数学更有效,因此更快吗?它是否能够展开循环(尽管这似乎不太可能产生如此巨大的差异)?
如果不是,您应该如何构建Java程序以从简单的循环和数学运算中获得最大性能?
编辑 - 感谢Dolda2000,我修改了Java版本。它现在的速度与GoLang版本大致相同。事实上,问题在于游戏的创建导致Java版本必须模拟更多游戏才能确定游戏是否足够长。随着这些变化,它现在在大约6秒内运行,并恢复了我对Java的信心。
更新 - 这是一篇扩展的文章,更详细地讨论了这个问题的背景。