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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2704417/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 11:02:34  来源:igfitidea点击:

Why is Go so slow (compared to Java)?

javaperformancegobenchmarking

提问by Oleg Razgulyaev

As we could see from The Computer Language Benchmarks Gamein 2010:

正如我们从2010 年的计算机语言基准游戏中看到的:

  • Go is on average 10x slower than C
  • Go is 3x slower than Java!?
  • Go 平均比C慢 10 倍
  • Go 比Java慢 3 倍!?

How can this be, bearing in mind that Go compiler produces native code for execution?
Immature compilers for Go? Or there is some intrinsic problem with the Go language?

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

EDIT:
Most answers deny intrinsic slowness of Go languge, claiming the problem resides in immature compilers.
Therefore I've made some own tests to calculate Fibonacci numbers: Iterative algorithm runs in Go (freebsd,6g) with the samespeed as in C (with O3 option). The dull recursive one runs in Go 2 timesslower than in C (with -O3 option; with -O0 - the same). But I haven't seen 10x fall as in the Benchmarks Game.

编辑:
大多数答案否认 Go 语言的内在缓慢,声称问题在于不成熟的编译器。
因此,我做了一些自己的测试来计算斐波那契数:迭代算法在 Go (freebsd,6g) 中以sameC 中的速度运行(使用 O3 选项)。枯燥的递归在 Go 中的运行2 times速度比在 C 中慢(使用 -O3 选项;使用 -O0 - 相同)。但我还没有看到像基准游戏那样下降 10 倍。

采纳答案by Steve Jessop

The 6g and 8g compilers are not particularly optimising, so the code they produce isn't particularly fast.

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

They're designed to run fast themselves and produce code that's OK (there is a bit of optimisation). gccgouses GCC's existing optimisation passes, and might provide a more pointful comparison with C, but gccgo isn't feature-complete yet.

它们旨在自己快速运行并生成正常的代码(有一些优化)。gccgo使用 GCC 现有的优化通道,并可能提供与 C 的更有意义的比较,但 gccgo 还不是功能完整的。

Benchmark figures are almost entirely about quality of implementation. They don't have a huge amount to do with the language as such, except to the extent that the implementation spends runtime supporting language features that the benchmark doesn't really need. In most compiled languages a sufficiently clever compiler could in theory strip out what isn't needed, but there comes a point where you're rigging the demo, since very few real users of the language would write programs that didn't use that feature. Moving things out of the way without removing them entirely (e.g. predicting virtual call destinations in JIT-compiled Java) starts to get tricky.

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

FWIW, my own very trivial test with Go when I was taking a look at it (a loop of integer addition, basically), gccgo produced code towards the fast end of the range between gcc -O0and gcc -O2for equivalent C. Go isn't inherently slow, but the compilers don't do everything, yet. Hardly surprising for a language that's 10 minutes old.

FWIW,我自己很琐碎与考验时,我正在看它(整数加法的循环,基本)围棋,gccgo产生对之间的范围内的快速结束码gcc -O0gcc -O2等效C.围棋是不是天生就慢,但是编译器还没有做所有的事情。对于 10 分钟前的语言来说,这不足为奇。

回答by peterSO

In the next release of the Go FAQ, something similar to the following should appear.

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

Performance

Why does Go perform badly on benchmark X?

One of Go's design goals is to approach the performance of C for comparable programs, yet on some benchmarks it does quite poorly, including several in test/bench. The slowest depend on libraries for which versions of comparable performance are not available in Go. For instance, pidigits depends on a multi-precision math package, and the C versions, unlike Go's, use GMP (which is written in optimized assembler). Benchmarks that depend on regular expressions (regex-dna, for instance) are essentially comparing Go's stopgap regexp package to mature, highly optimized regular expression libraries like PCRE.

Benchmark games are won by extensive tuning and the Go versions of most of the benchmarks need attention. If you measure comparable C and Go programs (reverse-complement is one example), you'll see the two languages are much closer in raw performance than this suite would indicate.

Still, there is room for improvement. The compilers are good but could be better, many libraries need major performance work, and the garbage collector isn't fast enough yet (even if it were, taking care not to generate unnecessary garbage can have a huge effect).

表现

为什么 Go 在基准 X 上表现不佳?

Go 的设计目标之一是在类似程序中接近 C 的性能,但在某些基准测试中它的表现相当糟糕,包括测试/基准测试中的几个。最慢的取决于在 Go 中没有可比性能版本的库。例如,pidigits 依赖于多精度数学包,而 C 版本与 Go 不同,使用 GMP(用优化的汇编程序编写)。依赖于正则表达式(例如 regex-dna)的基准测试本质上是将 Go 的权宜之计 regexp 包与成熟的、高度优化的正则表达式库(如 PCRE)进行比较。

基准游戏是通过广泛的调整赢得的,大多数基准的围棋版本需要注意。如果您测量可比较的 C 和 Go 程序(反向补码就是一个例子),您会发现这两种语言的原始性能比该套件显示的要接近得多。

尽管如此,仍有改进的余地。编译器很好,但可能会更好,许多库需要大量的性能工作,垃圾收集器还不够快(即使是这样,注意不要产生不必要的垃圾会产生巨大的影响)。

And here's some more details on The Computer Benchmarks Gamefrom a recent mailing list thread.

以下是最近的邮件列表线程中有关计算机基准测试游戏的更多详细信息。

Garbage collection and performance in gccgo (1)

gccgo中的垃圾收集与性能(一)

Garbage collection and performance in gccgo (2)

gccgo中的垃圾收集与性能(二)

It's important to note that the Computer Benchmarks Game is just a game. People with experience in performance measurement and capacity planning carefully match like with like over realistic and actual workloads; they don't play games.

需要注意的是,Computer Benchmarks Game 只是一个游戏。具有性能测量和容量规划经验的人员会仔细匹配现实和实际工作负载;他们不玩游戏。

回答by jdi

My answer isn't quite as technical as everyone else's, but I think it's still relevant. I saw the same benchmarks on the Computer Benchmarks Game when I decided to start learning Go. But I honestly think all these synthetic benchmarks are pointless in terms of deciding whether Go is fast enough for you.

我的回答不像其他人那么技术性,但我认为它仍然相关。当我决定开始学习围棋时,我在计算机基准测试游戏中看到了相同的基准测试。但老实说,我认为所有这些综合基准在决定 Go 是否对你来说足够快方面毫无意义。

I had written a message server in Python using Tornado+TornadIO+ZMQ recently, and for my first Go project I decided to rewrite the server in Go. So far, having gotten the server to the same functionality as the Python version, my tests are showing me about 4.7x speed increase in the Go program. Mind you, I have only been coding in Go for maybe a week, and I have been coding in Python for over 5 years.

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

Go is only going to get faster as they continue to work on it, and I think really it comes down to how it performs in a real world application and not tiny little computational benchmarks. For me, Go apparently resulted in a more efficient program than what I could produce in Python. That is my take on the answer to this question.

Go 只会随着他们继续努力而变得更快,我认为这实际上归结为它在现实世界应用程序中的表现,而不是微小的计算基准。对我来说,Go 显然产生了比我用 Python 生成的程序更高效的程序。这就是我对这个问题的回答的看法。

回答by Bill C

Both Java and C are more explicit with their data and method (function) definitions. C is statically typed, and Java is less so with its inheritance model. This means that the way the data will be handled is pretty much defined during the compilation.

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

Go is more implicit with its data and function definitions. The built in functions are more general in nature, and the lack of a type hierarchy (like Java or C++) gives Go a speed disadvantage.

Go 的数据和函数定义更加隐含。内置函数本质上更通用,缺乏类型层次结构(如 Java 或 C++)给 Go 带来了速度上的劣势。

Keep in mind that Google's goal for the Go language is to have an acceptable compromise between speed of execution and speed of coding. I think they are hitting a good sweet spot on their early attempt, and things will only improve as more work is done.

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

If you compare Go with more dynamically typed languages whose main advantage is speed of coding, you will see the execution speed advantage of Go. Go is 8 times faster than perl, and 6 times faster than Ruby 1.9 and Python 3 on those benchmarks you used.

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

Anyway the better question to ask is Go a good compromise in ease of programming versus speed of execution? My answer being yes and it should get better.

无论如何,要问的更好的问题是 Go 在易于编程与执行速度之间取得了很好的折衷?我的回答是肯定的,它应该会变得更好。

回答by R.Moeller

I think an often overlooked fact is, that JIT compilation can be > static compilation especially for (runtime) late bound functions or methods. The hotspot JIT decides at RUNTIME which methods to inline, it even might adjust data layout to the cache size/architecture of the CPU it is currently running on. C/C++ in general can make up (and overall will still perform better) by having direct access to the hardware. For Go things might look different as its more high-level compared to C, but currently lacks a runtime optimization system/compiler. My gut tells me, Go couldbe faster then Java as Go does not enforce pointer chasing that much and encourages better data structure locality + requires less allocation.

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

回答by DLopes

Despite the not so good efficiency of Go about the CPU cycles usage, the Go concurrency model is much faster than the thread model in Java, for instance, and can be comparable to C++ thread model.

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

Note that in the thread-ring benchmark, Go was 16xfaster than Java. In the same scenario Go CSP was almost comparable to C++, but using 4x less memory.

请注意,在线程环基准测试中,Go比 Java 快16 倍。在相同的场景中,Go CSP 几乎与 C++ 相当,但使用的内存少 4 倍。

The great power of Go language is its concurrency model, Communicating Sequential Processes, CSP, specified by Tony Hoare in 70's, being simple to implement and fit for highly concurrent needs.

Go 语言的强大之处在于它的并发模型,Communicating Sequential Processes,CSP,由 Tony Hoare 在 70 年代指定,易于实现并适合高度并发的需求。

回答by tiffon

Things have changed.

事情变了。

I think the current correct answer to your question is to contest the notion that go is slow. At the time of your inquiry your judgement was justified, but go has since gained a lot of ground in terms of performance. Now, it's still not as fast as C, but is no where near being 10x slower, in a general sense.

我认为目前对您的问题的正确答案是质疑 go 很慢的概念。在您询问时,您的判断是合理的,但此后 go 在性能方面取得了很大进展。现在,它仍然不如 C 快,但从一般意义上讲,它的速度远不及 C 的 10 倍。

Computer language benchmarks game

计算机语言基准测试游戏

At the time of this writing:

在撰写本文时:

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%

Though, it does suffer brutally on the binary tree benchmark:

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

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%

回答by robert engels

There are two basic reasons that that Java is faster than Go and C++, and can be faster than C in many cases:

Java 比 Go 和 C++ 快有两个基本原因,并且在很多情况下可以比 C 快:

1) The JIT compiler. It can inline virtual function calls through multiple levels, even with OO classes, based on the runtime profile. This is not possible in a statically compiled language (although the newer re-compilation based on recorded profile can help). This is very important to most benchmarks that involve repetitive algorithms.

1) JIT 编译器。它可以基于运行时配置文件通过多个级别内联虚拟函数调用,甚至可以使用 OO 类。这在静态编译语言中是不可能的(尽管基于记录的配置文件的较新的重新编译可以提供帮助)。这对于大多数涉及重复算法的基准测试非常重要。

2) The GC. GC based memory allocation is nearly free, as compared to malloc. And the 'free' penalty can be amortized across the entire runtime - often skipped because the program terminates before all garbage needs to be collected.

2) GC。与 malloc 相比,基于 GC 的内存分配几乎是免费的。并且“免费”惩罚可以在整个运行时分摊 - 通常被跳过,因为程序在需要收集所有垃圾之前终止。

There are hundreds (thousands?) of extremely talented developers making the GC/JVM efficient. Thinking you can "code better than all of them" is a folly. It is a human ego problem at its heart - humans have a hard time accepting that with proper training by talented humans, the computer is going to perform better than the humans that programmed it.

有数百名(数千名?)非常有才华的开发人员使 GC/JVM 高效。认为你可以“比他们所有人都写得更好”是一种愚蠢的想法。它的核心是人类的自我问题——人类很难接受,通过有才华的人类的适当训练,计算机将比编程的人类表现得更好。

Btw, C++ can be as fast as C if you don't use and of the OO features, but then you are pretty close to just programming in C to begin with.

顺便说一句,如果您不使用 OO 特性,C++ 可以和 C 一样快,但是您几乎可以从 C 开始编程。

Most importantly, the "speed differences" in these tests are usually meaningless. The IO costs are orders of magnitude more than the performance differences, and so proper designs that minimize IO costs always win - even in a interpreted language. Very few systems are CPU bound.

最重要的是,这些测试中的“速度差异”通常毫无意义。IO 成本比性能差异大几个数量级,因此最小化 IO 成本的适当设计总是获胜 - 即使在解释语言中也是如此。很少有系统受 CPU 限制。

As a final note, people refer to the "computer language benchmarks game" as a "scientific measure". The tests are completely flawed, For example, if you view the Java tests for nbody. When I run the tests on the same OS/hardware, I get roughly 7.6 secs for Java, and 4.7 secs for C - which is reasonable - not the 4x slowness the tests reports. It is click-bait, fake news, designed to generate site traffic.

最后,人们将“计算机语言基准测试游戏”称为“科学衡量标准”。测试完全有缺陷,例如,如果您查看 nbody 的 Java 测试。当我在相同的操作系统/硬件上运行测试时,我得到了大约 7.6 秒的 Java 和 4.7 秒的 C - 这是合理的 - 而不是测试报告的 4 倍慢。它是点击诱饵,虚假新闻,旨在产生网站流量。

As a final, final note... I ran the tests using Go, and it was 7.9 secs. The fact that when you click on Go, it compares it to Java, and when you click on Java it compares it to C, should be a red flag to any serious engineer.

最后,最后一点……我使用 Go 运行测试,它是 7.9 秒。当您单击 Go 时,它会将其与 Java 进行比较,而当您单击 Java 时,它会将其与 C 进行比较,这一事实对于任何认真的工程师来说都应该是一个危险信号。

For a real world comparison of Java, Go, and C++ see https://www.biorxiv.org/content/10.1101/558056v1spoiler alert, Java comes out on top in raw performance, with Go coming out on top with combined memory use and wall time.

有关 Java、Go 和 C++ 的真实世界比较,请参阅https://www.biorxiv.org/content/10.1101/558056v1剧透警告,Java 在原始性能方面名列前茅,而 Go 在内存使用方面名列前茅和墙壁时间。

回答by Dan Marinescu

As a matter of fact, Go is not only elegant and efficient at design time, but also super performant at run-time. The key is to use the right operating system i.e. LINUX. Performance profiling result under Windows and Mac OS are, for lack of a better word, one or two orders of magnitude inferior.

事实上,Go 不仅在设计时优雅高效,而且在运行时性能也非常出色。关键是使用正确的操作系统,即 LINUX。Windows 和 Mac OS 下的性能分析结果,没有更好的词,差一两个数量级。

回答by Dan Marinescu

under linux, the go runtime is super fast, perfectly comparable with c/c++. the go runtime under windows and unix are not in the same league

在linux下,go运行速度超快,完全可以和c/c++媲美。windows下和unix下的go运行时不在一个档次

comparison with java is not so important, go is for both system and application development (as java is more like blue collar for application development only). will not enter in details, but when things like kubernetes are written in go, you realize that is not an enterprise consultant friendly toy

和java比较不是那么重要,go是系统和应用开发的(因为java更像是只做应用开发的蓝领)。不会详细介绍,但是当 kubernetes 之类的东西用 go 写的时候,你会发现这不是一个企业顾问友好的玩具

i do not remember google mentioning even once about the compromise you refer to. go is well design, simple, elegant and efficient for for designing system and application level programs, has pointers, efficient memory allocation and deallocation, avoids complications arising from oh so easy to miss-use implementation inheritance, giving you co-routines and other modern ways to write high performance applications in time and budget. again, go is super fast under linux, which is exactly what it was designed for (very happy that it does)

我不记得谷歌甚至一次提到你提到的妥协。go 设计精良,简单、优雅、高效,用于设计系统和应用程序级程序,具有指针,高效的内存分配和释放,避免了容易误用的实现继承带来的复杂性,为您提供协程和其他现代在时间和预算内编写高性能应用程序的方法。再说一次,在 linux 下 go 速度非常快,这正是它的设计目的(很高兴它做到了)