购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.3 Go“快”吗

最近,许多公司都将自己的产品(如从Ruby、Python和Java)重写为Go [17] 。人们反复提到改用Go或用Go启动新项目的两个原因是可读性强和性能出色。可读性来自简单性和一致性(见2.1.8节),这也是Go的优势所在。但性能如何呢?与Python、Java或C++等语言相比,Go的速度快吗?

在笔者看来,这个问题问得不好。只要有时间和足够的空间,任何语言都可以在机器和操作系统允许的范围内达到最快的速度。这是因为,我们编写的代码最终会被编译成机器代码,并准确使用CPU的指令。此外,大多数语言都允许将执行委托给其他进程,例如用优化的汇编语言编写。不幸的是,有时我们用来判断一种语言是否“快”的唯一依据就是原始的、半优化的微程序基准,即比较不同语言的执行时间和内存使用情况。虽然这能告诉我们一些信息,但并不能有效说明实际问题,例如为了效率而进行的编程有多复杂 [18]

相反,我们应该从编写高效代码(而不仅仅是快速)的难度和实用性,以及这种过程会牺牲多少可读性和可靠性的角度来看待编程语言。笔者认为,Go语言在这些要素之间取得了出色的平衡,同时保持了编写基本功能代码的快速和简单。

能够更轻松地编写高效代码的原因之一是密封编译阶段,Go运行时中相对较少的未知数(参见2.2.3节)、易于使用的并发框架以及成熟的调试、基准测试和剖析工具(在第8章和第9章中讨论)。这些“Go特性”并不是凭空出现的。没有多少人知道,Go是站在巨人(C、Pascal和CSP)的肩膀上设计出来的。

1960年,来自美国和欧洲的语言专家联手创建了Algol 60。1970年,Algol树分裂为C和Pascal分支。40年后,这两个分支在Go中再次结合。

——Robert Griesemer,“The Evolution of Go”( https://oreil.ly/a4V1e

如图2-2所示,第1章中提到的许多名字都是Go的祖先。Hoare爵士创建的伟大的并发语言CSP,Wirth创建的Pascal声明和包,以及C语言的基本语法都为Go的今天做出了贡献。

但并非所有东西都是完美的。在效率方面,Go有其自身的弱点。正如你将在5.5节中了解到的,内存使用有时很难控制。程序中的分配可能会出人意料(特别是对新用户),垃圾收集自动内存释放过程有一些开销和最终行为。特别是对于数据密集型应用程序,要像具有严格限制的RAM容量的机器(例如物联网一样),努力确保内存或CPU效率。

图2-2:Go的宗谱

然而,将这一过程自动化的决定是非常有益的,它可以让程序员不必担心内存清理问题,而事实证明,内存清理甚至更糟糕,有时甚至是灾难性的(例如,两次释放内存)。其他语言使用的替代机制的一个很好的例子是Rust。它实现了一种独特的内存所有权模型,取代了自动全局垃圾回收。不幸的是,虽然Rust更高效,但用它编写代码却比Go复杂得多。这就是为什么我们看到Go的采用率更高。这反映了Go团队在这一要素上对易用性的权衡。

幸运的是,有一些方法可以减轻Go中垃圾回收机制对性能造成的负面影响,使我们的软件保持精简和高效。我们将在接下来的章节中介绍这些方法。 LKx/XDnhVArPiphbrghI874g2Rc1PAHODEOwo2d+FQx5sebcMjrj7R6r2iyrnpqm

点击中间区域
呼出菜单
上一章
目录
下一章
×