How does Go compile so quickly?

2019-01-29 16:15发布

I've Googled and poked around the Go website, but I can't seem to find an explanation for Go's extraordinary build times. Are they products of the language features (or lack thereof), a highly optimized compiler, or something else? I'm not trying to promote Go; I'm just curious.

11条回答
小情绪 Triste *
2楼-- · 2019-01-29 17:02

Go was designed to be fast, and it shows.

  1. Dependency Management: no header file, you just need to look at the packages that are directly imported (no need to worry about what they import) thus you have linear dependencies.
  2. Grammar: the grammar of the language is simple, thus easily parsed. Although the number of features is reduced, thus the compiler code itself is tight (few paths).
  3. No overload allowed: you see a symbol, you know which method it refers to.
  4. It's trivially possible to compile Go in parallel because each package can be compiled independently.

Note that GO isn't the only language with such features (modules are the norm in modern languages), but they did it well.

查看更多
再贱就再见
3楼-- · 2019-01-29 17:06

A good test for the translation efficiency of a compiler is self-compilation: how long does it take a given compiler to compile itself? For C++ it takes a very long time (hours?). By comparison, a Pascal/Modula-2/Oberon compiler would compile itself in less than one second on a modern machine [1].

Go has been inspired by these languages, but some of the main reasons for this efficiency include:

  1. A clearly defined syntax that is mathematically sound, for efficient scanning and parsing.

  2. A type-safe and statically-compiled language that uses separate compilation with dependency and type checking across module boundaries, to avoid unnecessary re-reading of header files and re-compiling of other modules - as opposed to independent compilation like in C/C++ where no such cross-module checks are performed by the compiler (hence the need to re-read all those header files over and over again, even for a simple one-line "hello world" program).

  3. An efficient compiler implementation (e.g. single-pass, recursive-descent top-down parsing) - which of course is greatly helped by points 1 and 2 above.

These principles have already been known and fully implemented in the 1970s and 1980s in languages like Mesa, Ada, Modula-2/Oberon and several others, and are only now (in the 2010s) finding their way into modern languages like Go (Google), Swift (Apple), C# (Microsoft) and several others.

Let's hope that this will soon be the norm and not the exception. To get there, two things need to happen:

  1. First, software platform providers such as Google, Microsoft and Apple should start by encouraging application developers to use the new compilation methodology, while enabling them to re-use their existing code base. This is what Apple is now trying to do with the Swift programming language, which can co-exist with Objective-C (since it uses the same runtime environment).

  2. Second, the underlying software platforms themselves should eventually be re-written over time using these principles, while simultaneously redesigning the module hierarchy in the process to make them less monolithic. This is of course a mammoth task and may well take the better part of a decade (if they are courageous enough to actually do it - which I am not at all sure in the case of Google).

In any case, it's the platform that drives language adoption, and not the other way around.

References:

[1] http://www.inf.ethz.ch/personal/wirth/ProjectOberon/PO.System.pdf, page 6: "The compiler compiles itself in about 3 seconds". This quote is for a low cost Xilinx Spartan-3 FPGA development board running at a clock frequency of 25 MHz and featuring 1 MByte of main memory. From this one can easily extrapolate to "less than 1 second" for a modern processor running at a clock frequency well above 1 GHz and several GBytes of main memory (i.e. several orders of magnitude more powerful than the Xilinx Spartan-3 FPGA board), even when taking I/O speeds into account. Already back in 1990 when Oberon was run on a 25MHz NS32X32 processor with 2-4 MBytes of main memory, the compiler compiled itself in just a few seconds. The notion of actually waiting for the compiler to finish a compilation cycle was completely unknown to Oberon programmers even back then. For typical programs, it always took more time to remove the finger from the mouse button that triggered the compile command than to wait for the compiler to complete the compilation just triggered. It was truly instant gratification, with near-zero wait times. And the quality of the produced code, even though not always completely on par with the best compilers available back then, was remarkably good for most tasks and quite acceptable in general.

查看更多
不美不萌又怎样
4楼-- · 2019-01-29 17:06

Simply ( in my own words ), because the syntax is very easy ( to analyze and to parse )

For instance, no type inheritance means, not problematic analysis to find out if the new type follows the rules imposed by the base type.

For instance in this code example: "interfaces" the compiler doesn't go and check if the intended type implement the given interface while analyzing that type. Only until it's used ( and IF it is used ) the check is performed.

Other example, the compiler tells you if you're declaring a variable and not using it ( or if you are supposed to hold a return value and you're not )

The following doesn't compile:

package main
func main() {
    var a int 
    a = 0
}
notused.go:3: a declared and not used

This kinds of enforcements and principles make the resulting code safer, and the compiler doesn't have to perform extra validations that the programmer can do.

At large all these details make a language easier to parse which result in fast compilations.

Again, in my own words.

查看更多
Animai°情兽
5楼-- · 2019-01-29 17:08

i think Go was designed in parallel with compiler creation, so they were best friends from birth. (IMO)

查看更多
Melony?
6楼-- · 2019-01-29 17:10

Compilation efficiency was a major design goal:

Finally, it is intended to be fast: it should take at most a few seconds to build a large executable on a single computer. To meet these goals required addressing a number of linguistic issues: an expressive but lightweight type system; concurrency and garbage collection; rigid dependency specification; and so on. FAQ

The language FAQ is pretty interesting in regards to specific language features relating to parsing:

Second, the language has been designed to be easy to analyze and can be parsed without a symbol table.

查看更多
登录 后发表回答