为什么Go这么慢(与Java相比)?

时间:2010-04-24 12:16:49

标签: java performance go benchmarking

正如我们在2010年The Computer Language Benchmarks Game所看到的那样:

  • Go平均比C
  • 慢10倍
  • Go比Java慢3倍!?

这怎么可能,记住Go编译器生成用于执行的本机代码?
Go的不成熟的编译器?或者Go语言存在一些内在问题?

编辑:
大多数答案否认Go语言的内在缓慢,声称问题存在于不成熟的编译器中 因此我做了一些自己的测试to calculate Fibonacci numbers:迭代算法在Go(freebsd,6g)中以same速度运行,如在C中(使用O3选项)。沉闷的递归运行在Go 2 times中比在C中慢(使用-O3选项;使用-O0 - 相同)。但我没有看到基准游戏中的10倍跌幅。

9 个答案:

答案 0 :(得分:101)

6g和8g编译器没有特别优化,因此它们生成的代码不是特别快。

它们被设计为自己快速运行并生成可以正常运行的代码(有一些优化)。 gccgo使用GCC现有的优化传递,可能会提供与C更有意义的比较,但gccgo尚未完成功能。

基准数字几乎完全与实施质量有关。它们与语言本身并没有太大关系,除非实现花费运行时支持基准测试并不真正需要的语言功能。在大多数编译语言中,一个足够聪明的编译器理论上可以删除不需要的东西,但是有一个点你需要操作演示,因为很少有真正的语言用户会编写没有使用该功能的程序。在不完全删除它们的情况下将事物移开(例如,在JIT编译的Java中预测虚拟调用目标)开始变得棘手。

FWIW,当我看一下它(基本上是一个整数加法循环)时,我用Go进行的非常微不足道的测试,gccgo在gcc -O0和{{1}之间的范围的快速结束处生成代码对于等效的C. Go本身并不慢,但编译器并没有做任何事情。对于一种10分钟的语言来说,这简直令人惊讶。

答案 1 :(得分:50)

Go FAQ的下一个版本中,应出现类似于以下内容的内容。

  

性能

     

为什么Go在基准测试中表现不佳   X?

     

Go的设计目标之一是   接近C的表现   可比较的计划,但有些   基准测试表现不佳,   包括几个在测试/工作台。该   最慢的依赖于库   性能相当的版本   Go中没有。例如,   pidigits取决于多精度   数学包和C版本,   与Go不同,使用GMP(已编写   在优化的汇编程序中)。基准   这取决于正则表达式   (例如regex-dna)   基本上比较Go的权宜之计   regexp包成熟,高度   优化的正则表达式库   像PCRE。

     

广泛赢得基准游戏   调整和大多数的Go版本   基准需要注意。如果你   衡量可比的C和Go计划   (反向补充就是一个例子),   你会看到这两种语言很多   原始性能比这更接近   套房会表明。

     

尽管如此,还有改进的余地。   编译器很好,但可能   更好,许多图书馆需要专业   表现工作,和垃圾   收藏家还不够快(甚至   如果是的话,请注意不要   生成不必要的垃圾可以有   一个巨大的影响)。

以下是来自最近邮件列表主题的The Computer Benchmarks Game的更多详细信息。

Garbage collection and performance in gccgo (1)

Garbage collection and performance in gccgo (2)

重要的是要注意计算机基准游戏只是一款游戏。具有性能测量和容量规划经验的人员可以像现实和实际工作负载一样仔细匹配;他们不玩游戏。

答案 2 :(得分:33)

我的答案并不像其他人那样技术性,但我认为它仍然具有相关性。 当我决定开始学习Go时,我在计算机基准游戏中看到了相同的基准。但老实说,我认为所有这些综合基准测试对于判断Go是否足够快而言毫无意义。

我最近使用Tornado + TornadIO + ZMQ用Python编写了一个消息服务器,对于我的第一个Go项目,我决定用Go重写服务器。到目前为止,让服务器具有与Python版本相同的功能,我的测试向我展示了Go程序中4.7倍的速度提升。请注意,我只在Go中编写了一个星期的编码,而且我已经用Python编写了超过5年的编码。

Go只会在它们继续工作时变得更快,我认为它实际上归结为它在现实世界的应用程序中的表现,而不是微小的计算基准。对我来说,Go显然比我在Python中生成的程序更有效。这是我对这个问题的回答。

答案 3 :(得分:6)

事情发生了变化。

我认为目前对你的问题的正确答案是反对这样做的观点。在你的询问时,你的判断是合理的,但从那以后,在表现方面取得了很多进展。现在,它仍然没有C那么快,但在一般意义上,它不会慢10倍。

Computer language benchmarks game

撰写本文时:

source  secs    KB      gz      cpu     cpu load

reverse-complement
1.167x
Go      0.49    88,320  1278    0.84    30% 28% 98% 34%
C gcc   0.42    145,900 812     0.57    0% 26% 20% 100%

pidigits
1.21x
Go      2.10    8,084   603 2.10    0% 100% 1% 1%
C gcc   1.73    1,992   448 1.73    1% 100% 1% 0%

fasta
1.45x
Go      1.97    3,456   1344    5.76    76% 71% 74% 73%
C gcc   1.36    2,800   1993    5.26    96% 97% 100% 97%

regex-dna
1.64x
Go      3.89    369,380 1229    8.29    43% 53% 61% 82%
C gcc   2.43    339,000 2579    5.68    46% 70% 51% 72%

fannkuch-redux
1.72x
Go      15.59   952 900 62.08   100% 100% 100% 100%
C gcc   9.07    1,576   910 35.43   100% 99% 98% 94%

spectral-norm
2x
Go      3.96    2,412   548 15.73   99% 99% 100% 99%
C gcc   1.98    1,776   1139    7.87    99% 99% 100% 99%

n-body
2.27x
Go      21.73   952 1310    21.73   0% 100% 1% 2%
C gcc   9.56    1,000   1490    9.56    1% 100% 1% 1%

k-nucleotide
2.40x
Go      15.48   149,276 1582    54.68   88% 97% 90% 79%
C gcc   6.46    130,076 1500    17.06   51% 37% 89% 88%

mandelbrot
3.19x
Go      5.68    30,756  894 22.56   100% 100% 99% 99%
C gcc   1.78    29,792  911 7.03    100% 99% 99% 98%

尽管如此,它确实在二叉树基准测试中遭受了残酷的打击:

binary-trees
12.16x
Go      39.88   361,208 688 152.12  96% 95% 96% 96%
C gcc   3.28    156,780 906 10.12   91% 77% 59% 83%

答案 4 :(得分:5)

尽管Go的CPU周期使用效率不高,但Go并发模型比Java中的线程模型快得多,并且可以与C ++线程模型相媲美。

请注意,在thread-ring benchmark中,Go比Java强 16x 。在同一场景中,Go CSP几乎与C ++相当,但使用的内存减少了4倍。

Go语言的强大功能是它的并发模型,通信顺序进程,CSP,由Tony Hoare在70年代指定,易于实现并适合高度并发的需求。

答案 5 :(得分:1)

我认为一个经常被忽视的事实是,JIT编译可以是>静态编译,尤其适用于(运行时)后期绑定函数或方法。热点JIT在RUNTIME决定采用哪种内联方法,甚至可以将数据布局调整为当前运行的CPU的高速缓存大小/体系结构。 通过直接访问硬件,C / C ++通常可以弥补(并且总体上仍将表现更好)。对于Go来说,事物可能看起来不同,因为它与C相比更高级,但目前缺少运行时优化系统/编译器。 我的直觉告诉我,Go 可以比Java更快,因为Go不强制指针追逐那么多,并鼓励更好的数据结构局部性+需要更少的分配。

答案 6 :(得分:0)

在Linux下,go运行时非常快,可以与c / c ++完美媲美。 Windows和Unix下的go运行时不在同一个

与Java的比较不是很重要,go既适用于系统开发,也适用于应用程序开发(因为Java更像是仅用于应用程序开发的蓝领)。不会输入详细信息,但是当您在编写gobernetes之类的东西时,您会意识到这不是企业顾问友好的玩具

我什至不记得有一次Google提及您提及的妥协。 go是精心设计的,简单,优雅且高效的设计系统和应用程序的程序,具有指针,有效的内存分配和释放,避免了因易于实现的继承而容易产生的复杂问题,从而为您提供了协同例程和其他现代方法时间和预算编写高性能应用程序的方法。再说一次,go在linux下超级快,这正是它的设计目标(对此非常高兴)

答案 7 :(得分:-1)

事实上,Go在设计时不仅优雅高效,而且在运行时也表现出色。关键是使用正确的操作系统,如LINUX。由于缺乏更好的说法,Windows和Mac OS下的性能分析结果要差一个或两个数量级。

答案 8 :(得分:-4)

Java和C在数据和方法(函数)定义方面都更加明确。 C是静态类型的,其继承模型的Java较少。这意味着在编译期间几乎定义了数据的处理方式。

Go的数据和函数定义更加隐含。内置函数本质上更通用,缺少类型层次结构(如Java或C ++)使Go速度不利。

请记住,Google的Go语言目标是在执行速度和编码速度之间达成可接受的折衷。我认为他们在早期尝试中找到了一个很好的甜蜜点,只有做更多的工作才会有所改善。

如果将Go与更具动态类型的语言进行比较,其主要优点是编码速度,您将看到Go的执行速度优势。在你使用的那些基准测试中,Go比perl快8倍,比Ruby 1.9和Python 3快6倍。

无论如何,更好的问题是在编程的简易性和执行速度方面做出妥协?我的答案是肯定的,它应该会变得更好。