乐闻世界logo
搜索文章和话题

Golang 的编译速度为什么这么快?

9 个月前提问
5 个月前修改
浏览次数188

6个答案

1
2
3
4
5
6

Golang(通常称为Go)的编译速度之所以快,主要是归功于以下几个设计决策和特性:

  1. 简化的依赖模型:Go具有明确的依赖模型,每个文件都声明了它的直接依赖项。这种模型简化了依赖关系的管理,并且使得编译器能够快速确定哪些文件需要重新编译,哪些不需要。

  2. 包模型:Go的包模型也有助于加快编译速度。每个包被编译成一个单独的二进制文件,只有当包的源文件发生变化时才需要重新编译,而不是像一些其他语言那样需要重新编译整个项目。

  3. 并发编译:Go编译器被设计成能够利用现代多核处理器。它可以并发地编译不同的文件和包,最大化利用CPU资源,从而减少编译时间。

  4. 简化的语言特性:Go的设计哲学是简洁和清晰,避免了复杂的语言特性,例如类继承。这些简化的特性意味着编译器有更少的工作要做,因此编译过程可以更快完成。

  5. 快速解析的语法:Go的语法设计使得代码可以快速且一次性解析,减少了编译过程中的回溯。这使得语法分析阶段非常高效。

  6. 直接生成机器代码:Go编译器直接生成目标平台的机器代码,而不是像其他语言(如Java或C#)那样生成中间字节码。这样可以避免运行时解释或即时编译,提高编译效率。

  7. 编译器优化:Go编译器经过了优化,以便快速处理代码。这包括对语言特性进行了优化,使得编译器能够有效地生成代码。

举个例子,如果你在一个大型Go项目中只修改了一个小的包,Go编译器会识别出只有这个包及其依赖需要重新编译。由于它可以并发编译独立的包,并且每个包编译后都是独立的二进制文件,这意味着整个编译过程只需要很短的时间就可以完成。

因此,Go的快速编译是多种因素综合作用的结果,这些因素共同构成了Go语言快速且高效编译过程的基础。

2024年6月29日 12:07 回复

依赖性分析。

Go FAQ曾经包含以下句子:

Go 提供了一个软件构建模型,使依赖性分析变得容易,并避免了 C 风格包含文件和库的大部分开销。

虽然该短语不再出现在常见问题解答中,但该主题在Google 的 Go演讲中进行了详细阐述,该演讲比较了 C/C++ 和 Go 的依赖分析方法。

这是编译速度快的主要原因。这是设计使然。

2024年6月29日 12:07 回复

我认为并不是Go编译器_快_,而是其他编译器_慢_。

C 和 C++ 编译器必须解析大量的标头 - 例如,编译 C++“hello world”需要编译 18k 行代码,这几乎是半兆字节的源代码!

shell
$ cpp hello.cpp | wc 18364 40513 433334

Java 和 C# 编译器在 VM 中运行,这意味着在编译任何内容之前,操作系统必须加载整个 VM,然后必须将它们从字节码 JIT 编译为本机代码,所有这些都需要一些时间。

编译速度取决于几个因素。

有些语言被设计为可以快速编译。例如,Pascal 被设计为使用单遍编译器进行编译。

编译器本身也可以优化。例如,Turbo Pascal 编译器是用手工优化的汇编程序编写的,与语言设计相结合,产生了在 286 级硬件上运行的非常快的编译器。我认为即使是现在,现代 Pascal 编译器(例如 FreePascal)也比 Go 编译器更快。

2024年6月29日 12:07 回复

Go 编译器比大多数 C/C++ 编译器快得多的原因有多种:

  • 主要原因:大多数 C/C++ 编译器的设计都非常糟糕(从编译速度的角度来看)。此外,从编译速度的角度来看,C/C++ 生态系统的某些部分(例如程序员编写代码的编辑器)在设计时并未考虑编译速度。

  • 首要原因:快速编译速度是 Go 编译器和 Go 语言的一个有意识的选择

  • Go 编译器比 C/C++ 编译器有更简单的优化器

  • 与 C++ 不同,Go 没有模板,也没有内联函数。这意味着 Go 不需要执行任何模板或函数实例化。

  • Go 编译器会更快地生成低级汇编代码,优化器会处理汇编代码,而在典型的 C/C++ 编译器中,优化过程会处理原始源代码的内部表示。C/C++ 编译器中的额外开销来自需要生成内部表示的事实。

  • Go 程序的最终链接 (5l/6l/8l) 可能比链接 C/C++ 程序慢,因为 Go 编译器会遍历所有使用的汇编代码,并且可能还会执行 C/C++ 所不具备的其他额外操作链接器没有做

  • 一些 C/C++ 编译器 (GCC) 以文本形式生成指令(将传递给汇编器),而 Go 编译器以二进制形式生成指令。需要完成额外的工作(但不多)才能将文本转换为二进制。

  • Go编译器仅针对少量CPU架构,而GCC编译器针对大量CPU

  • 以高编译速度为目标的编译器(例如 Jikes)速度很快。在 2GHz CPU 上,Jikes 每秒可以编译 20000+ 行 Java 代码(增量编译模式效率更高)。

2024年6月29日 12:07 回复

编译效率是一个主要设计目标:

最后,它的目的是要快速:在一台计算机上构建一个大型可执行文件最多需要几秒钟。为了实现这些目标,需要解决许多语言问题:富有表现力但轻量级的类型系统;并发和垃圾收集;严格的依赖规范;等等。常问问题

关于与解析相关的特定语言功能,语言常见问题解答非常有趣:

其次,该语言被设计为易于分析,无需符号表即可解析。

2024年6月29日 12:07 回复

虽然上面的大部分内容都是正确的,但有一个非常重要的点没有真正提到:依赖管理。

_Go 只需要包含您直接_导入的包(因为那些已经导入了_它们_需要的包)。这与 C/C++ 形成鲜明对比,C/C++ 中每个文件开始都包含 x 个标头,其中包括 y 标头等。底线:Go 的编译时间与导入包的数量呈线性关系,而 C/C++ 则需要指数时间。

2024年6月29日 12:07 回复

你的答案