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条回答
在下西门庆
2楼-- · 2019-01-29 16:45

Dependency analysis.

From the Go FAQ:

Go provides a model for software construction that makes dependency analysis easy and avoids much of the overhead of C-style include files and libraries.

That is the main reason of fast compilation. And this is by design.

查看更多
在下西门庆
3楼-- · 2019-01-29 16:48

I think it's not that Go compilers are fast, it's that other compilers are slow.

C and C++ compilers have to parse enormous amounts of headers - for example, compiling C++ "hello world" requires compiling 18k lines of code, which is almost half a megabyte of sources!

$ cpp hello.cpp | wc
  18364   40513  433334

Java and C# compilers run in a VM, which means that before they can compile anything, the operating system has to load the whole VM, then they have to be JIT-compiled from bytecode to native code, all of which takes some time.

Speed of compilation depends on several factors.

Some languages are designed to be compiled fast. For example, Pascal was designed to be compiled using a single-pass compiler.

Compilers itself can be optimized too. For example, the Turbo Pascal compiler was written in hand-optimized assembler, which, combined with the language design, resulted in a really fast compiler working on 286-class hardware. I think that even now, modern Pascal compilers (e.g. FreePascal) are faster than Go compilers.

查看更多
地球回转人心会变
4楼-- · 2019-01-29 16:51

Quoting from the book "The Go Programming Language" by Alan Donovan and Brian Kernighan:

Go compilation is notably faster than most other compiled languages, even when building from scratch. There are three main reasons for the compiler’s speed. First, all imports must be explicitly listed at the beginning of each source file, so the compiler does not have to read and process an entire file to determine its dependencies. Second, the dependencies of a package form a directed acyclic graph, and because there are no cycles, packages can be compiled separately and perhaps in parallel. Finally, the object file for a compiled Go package records export information not just for the package itself, but for its dependencies too. When compiling a package, the compiler must read one object file for each import but need not look beyond these files.

查看更多
淡お忘
5楼-- · 2019-01-29 16:52

While most of the above is true, there is one very important point that was not really mentionend: Dependency management.

Go only needs to include the packages that you are importing directly (as those already imported what they need). This is in stark contrast to C/C++, where every single file starts including x headers, which include y headers etc. Bottom line: Go's compiling takes linear time w.r.t to the number of imported packages, where C/C++ take exponential time.

查看更多
霸刀☆藐视天下
6楼-- · 2019-01-29 16:54

The basic idea of compilation is actually very simple. A recursive-descent parser, in principle, can run at I/O bound speed. Code generation is basically a very simple process. A symbol table and basic type system is not something that requires a lot of computation.

However, it is not hard to slow down a compiler.

If there is a preprocessor phase, with multi-level include directives, macro definitions, and conditional compilation, as useful as those things are, it is not hard to load it down. (For one example, I'm thinking of the Windows and MFC header files.) That is why precompiled headers are necessary.

In terms of optimizing the generated code, there is no limit to how much processing can be added to that phase.

查看更多
The star\"
7楼-- · 2019-01-29 17:02

There are multiple reasons why the Go compiler is much faster than most C/C++ compilers:

  • Top reason: Most C/C++ compilers exhibit exceptionally bad designs (from compilation speed perspective). Also, from compilation speed perspective, some parts of the C/C++ ecosystem (such as editors in which programmers are writing their codes) aren't designed with speed-of-compilation in mind.

  • Top reason: Fast compilation speed was a conscious choice in the Go compiler and also in the Go language

  • The Go compiler has a simpler optimizer than C/C++ compilers

  • Unlike C++, Go has no templates and no inline functions. This means that Go doesn't need to perform any template or function instantiation.

  • The Go compiler generates low-level assembly code sooner and the optimizer works on the assembly code, while in a typical C/C++ compiler the optimization passes work on an internal representation of the original source code. The extra overhead in the C/C++ compiler comes from the fact that the internal representation needs to be generated.

  • Final linking (5l/6l/8l) of a Go program can be slower than linking a C/C++ program, because the Go compiler is going through all of the used assembly code and maybe it is also doing other extra actions that C/C++ linkers aren't doing

  • Some C/C++ compilers (GCC) generate instructions in text form (to be passed to the assembler), while the Go compiler generates instructions in binary form. Extra work (but not much) needs to be done in order to transform the text into binary.

  • The Go compiler targets only a small number of CPU architectures, while the GCC compiler targets a large number of CPUs

  • Compilers which were designed with the goal of high compilation speed, such as Jikes, are fast. On a 2GHz CPU, Jikes can compile 20000+ lines of Java code per second (and the incremental mode of compilation is even more efficient).

查看更多
登录 后发表回答