为什么Golang比Scala慢?

25

在这个测试中,我们可以看到golang的性能有时比scala慢得多。我认为,由于golang的代码直接编译成c/c++兼容的二进制代码,而scala的代码编译成JVM字节码,因此golang应该具有更好的性能,特别是在这些计算密集型算法的基准测试中。我的理解是否不正确?

http://benchmarksgame.alioth.debian.org/u64/chartvs.php?r=eNoljskRAEEIAlPCA48ozD%2Bb1dkX1UIhzELXeGcih5BqXeksDvbs8Vgi9HFr23iGiD82SgxJqRWkKNctgkMVUfwlHXnZWDkut%2BMK1nGawoYeDLlYQ8eLG1tvF91Dd8NVGm4sBfGaYo0Pok0rWQ%3D%3D&m=eNozMFFwSU1WMDIwNFYoNTNRyAMAIvoEBA%3D%3D&w=eNpLz%2FcvTk7MSQQADkoDKg%3D%3D


2
那张图表并没有展示性能方面的信息,而是全部关于内存使用。你正在问错问题。 - wheaties
@user2864740 不是,它显示使用的内存。 - wheaties
1
更糟糕的是,某人编辑了帖子,删除了从中获取图表的测试的URL链接。虽然应该在其周围编写更多上下文,但现在没有任何机会让这些上下文可达。 - wheaties
2
@Tyr 看了那个链接,我发现大多数时间 Go 能够超过 Scala。虽然我不是 Go 的粉丝,但是这样的“基准测试”并不能很好地评估一门语言。你必须询问代码是否真正被优化,它是否运行足够长的时间以捕获真实的 GC 活动等等。 - wheaties
2
一般来说,JVM并不慢 - 现在已经有很长时间了。Go语言也进行垃圾回收、边界检查等操作。此外,它们显然没有进行非常广泛的编译时优化,而是以极快的编译时间为优先考虑因素。如果你想知道某个基准测试结果快或慢的原因,那么从整体上来推测并没有什么意义:如果你想知道,只需使用分析工具进行分析即可。 - 0x434D53
显示剩余3条评论
5个回答

58

以下是我对四个基准测试中Go解决方案相对Scala解决方案较慢的原因的看法。

  1. 曼德博集合(mandelbrot):Scala实现已将其内部循环展开了一次。这可能是JVM可以向量化计算的结果,而我认为Go编译器尚未做到。这是良好的手动优化和更好的JVM支持加速算术运算。
  2. 正则表达式-DNA(regex-dna):Scala实现没有按照基准测试要求执行:它要求"""(一次一个模式)匹配替换重定向文件中的模式,并记录序列长度"""",但它只是计算长度并打印。Go版本执行了匹配替换,因此速度较慢。
  3. k核苷酸(k-nucleotide):Scala实现通过位操作将核苷酸打包到一个长整型中进行了优化,而不是使用字符。这是一个很好的优化方法,也可以应用于Go代码。
  4. 二叉树(binary-trees):这个测试填充RAM以测试gc性能。确实,Java的gc比Go的gc快得多,但不把垃圾放入程序中通常可以避免在实际程序中使用gc,这就是不将其作为Go的最高优先级的原因。

2
Scala正则表达式DNA #5程序已被删除。 - igouy

20

这张图表来自编程 Shootout。在把基准测试结果当做真理之前,请先阅读 Shootout 页面上的免责声明。最好的情况下,这些基准测试只能用于指示性能的大致期望。

话虽如此,JVM 已经进行了十年的资金充裕的优化,在启动时间以外,提供了出色的运行代码性能。Go 仍然是一种年轻的语言。能够在性能上接近 JVM 语言是令人印象深刻的。如果你喜欢用 Go 编程,不应该因为一个基准测试而拒绝使用它。


我不是拒绝go语言。我只是对基准测试结果感到好奇。这些案例应该是纯计算密集型算法,而JVM可能没有太多帮助。由于go语言可以直接编译成二进制文件,因此它的性能应该与C语言相似。即使JVM中的JIT有多么快,它也不应该与本地代码相同。我也不太相信go语言仍然年轻 - 它已经开发了几年了。无论如何,似乎没有更好的解释。 - Tyr
3
并非所有编译语言运行速度都相同。Go 也许不会像 C 一样快(但差距将在未来缩小)。垃圾回收器、边界检查等是该语言的有用功能,但也会减慢执行时间。 - siritinga
在进行基准测试之前,您应该阅读Shootout页面上的免责声明。这些基准测试结果仅供参考。请不要将其视为绝对真实及准确的数据。同时,请遵循主页上的提示:"测量并非预言"。 - igouy

15
这在go的常见问题解答中有讨论:
一项Go的设计目标是在与C相媲美的程序中接近其性能,但在某些基准测试中它表现不佳,包括在test/bench/shootout中的几个基准测试。最慢的基准测试依赖于Go没有可比性能版本的库。例如,pidigits.go依赖于一个多精度数学包,而C版本,不像Go的版本,使用了优化汇编的GMP。依赖于正则表达式的基准测试(例如regex-dna.go)本质上在将Go的本地regexp包与成熟的、高度优化的正则表达式库(如PCRE)进行比较。
基准测试需要进行广泛调整,而大多数基准测试的Go版本需要关注。如果你测量可比的C和Go程序(reverse-complement.go是一个例子),你会发现这两种语言在原始性能上比这个套件所示的要接近得多。
尽管如此,还有改进的空间。编译器很好但可以更好,许多库需要进行重大性能工作,垃圾回收器还不够快。(即使是这样,注意不生成不必要的垃圾也可能产生巨大的影响。)

顺便提一下,考虑一下给定编程语言的不同版本基准测试之间的10x(!)速度差异。C gcc #7比C gcc #5慢8.3倍,而Ada #3几乎比Ada #5慢10倍。这些基准测试提供了语言之间比较的大致想法,但Go和Scala之间的差异在一个数量级内,这意味着运行时之间的任何“内在”变化可能会被实现差异所掩盖:此帖子描述了如何通过执行更智能的内存分配来加速程序11倍。也许编译器/运行时应该自动处理这种优化(JVM在某种程度上确实如此),但我不确定您是否真的可以从这些数字中得出“ Go比Scala慢(或快)”的结论。只是我的看法 :)


任何运行时之间的“固有”差异都可能会被实现上的差异所掩盖--不是“可能会”,而是“有可能”。 - igouy

11

既然你似乎很热衷于看这些有偏见的基准测试,那么让我们来看一个真实的例子,而不是一些斐波那契数列的实现。

请查看这些web框架基准测试排名,它们使用本地客户端(如果可用)和开源软件(web framework) 进行测试,并使用相同语言的许多包进行测试。 测试范围从对原始字符串的请求到使用ORM查询数据库。

显然,Scala的性能远远不及Go,在所有测试中Scala都低于Go。尽管如此,基准测试与现实情况有很大差异,我建议您从工具/功能的角度或仅从最好解决问题的角度考虑一种语言。


2
请仅返回翻译后的文本,不要进行解释。 - igouy
2
在更好的硬件(双路 Xeon E5 v2)上,Go 在 6 项测试中有 5 项比 Scala 更慢。JSON 序列化:Go 31.7%,Scala 纯文本 18.7%。 单个查询:Go 34.9%,Scala 54.2%。 多个查询:Go 37.4%,Scala 纯文本 78.2%。 Fortunes:Go 8.8%,Scala 纯文本 52.1%。 数据更新:Go 72.4%,Scala 纯文本 91.6%。 纯文本:Go 7.1%,Scala 纯文本 32.7%。http://www.techempower.com/benchmarks/previews/round9/#section=data-r9&hw=peak&test=json - rofrol
我不确定你在哪里看到这个,但当我查看性能结果时,Go比Scala领先得多: go 441,978 20.1% play-scala-anorm 181,316 8.2% http://www.techempower.com/benchmarks/#section=data-r12&hw=peak&test=json - Thomas Modeneis

4

正如Brad所指出的那样,这些结果来自于一个特定的基准测试套件。这提供了一些信息,但不要认为这是全部情况。了解源代码是否编写得足够好以提供最快的速度、最少的内存使用或其他目标目标将会很有帮助。

也许我们可以与另一个排名语言的网站进行比较。请看http://www.techempower.com/benchmarks/该网站对Web服务代码进行比较。尽管Go是一种年轻的语言,但在一些基准测试中表现最佳之一。

就像所有基准测试一样,它总是取决于您追求什么以及如何衡量它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接