Ben*_*ter 39 java performance go
最近在工作中,我们正在讨论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中的游戏(两者都在上面链接)的性能关键方法.
Go程序几乎是Java程序的文字副本,但其运行时间约为6秒,而Java程序约为26秒(在我的本地机器上).类似的数字被复制到其他几台机器上,Go程序的速度提高约5倍.
Go程序使用1.7.5和Java编译,使用版本1.8.0_65,两者都运行在2013年末带有2.6GHz i5 CPU的视网膜Macbook Pro上的macOS Sierra 10.12.3上.
为什么Go程序比Java程序快5倍,因为大多数基准测试表明Java应该在同一个运行时?它只是一个循环中的基本数学,所以看起来它们应该在大约相同的时间运行.我可以理解JVM启动时间的第二个左右,但这似乎是关闭的.
两个程序都使用几乎相同的循环.对于每个起始金额,创建并迭代所有可能的游戏结果排列.看来,对于主循环中的任意数量的循环操作,Go在Java周围运行环.
我知道这是一个"微观"基准测试,但我想知道为什么Go代码大大优于Java代码.Go for simple循环/数学是否更有效,因此更快?它是否能够展开循环(虽然这似乎不太可能产生如此巨大的差异)?
如果不是,您应该如何构建Java程序以从简单的循环和数学运算中获得最佳性能?
编辑 - 感谢Dolda2000我修改了Java版本.它现在与GoLang版本大致相同.事实上,问题在于游戏的创建导致Java版本必须模拟更多游戏以确定游戏是否足够长.随着变化,它现在运行大约6秒钟,并恢复了我对Java的信心.
更新 - 这是一篇扩展的文章,更详细地讨论了这个问题的背景.
Dol*_*000 47
事实证明,你的程序并不像你认为的那样平等.我指导他们看看他们模拟了多少场比赛(即个人投注轮次),而Go版本模拟了1 612 629 805场比赛,Java版本模拟了12 323 903 502场比赛,几乎要高出一个数量级.
在我的机器上,关闭多线程以获得更可预测的结果,Java程序在大约75秒内启动,Go程序在12.5秒内启动.与总运行时匹配,看起来Java程序实际上每个模拟游戏稍微快一点,大约6.1 ns,而Go程序则为7.8 ns.
但不确定为什么他们会模拟这么多不同数量的游戏.也许Go版本生成回合的方式恰好可以找到更快更快的终止.
编辑:实际上,最后一次猜测很有意义.Go版本通过调整游戏的初始轮次开始,而Java版本则通过调整游戏的最后几轮开始(换句话说,将轮次列表视为增加的11位数基数列表-3数字,Go版本是little-endian,而Java版本是big-endian,可以这么说),因此Java版本必须通过更多相同的开始来模拟终止的变体.我没有尝试验证这个假设,但我确信我认为没有必要.