我在谷歌上搜索了一下Go的网站,但我找不到Go非凡的构建时间的解释。它们是语言特性(或缺乏特性)的产物、高度优化的编译器还是其他什么?我并不是在推广围棋;我只是好奇。
当前回答
测试编译器翻译效率的一个很好的方法是自编译:给定的编译器编译自己需要多长时间?对于c++来说,这需要很长的时间(几个小时?)相比之下,在现代机器[1]上,Pascal/Modula-2/Oberon编译器将在不到一秒钟的时间内自行编译。
Go一直受到这些语言的启发,但这种效率的一些主要原因包括:
A clearly defined syntax that is mathematically sound, for efficient scanning and parsing. 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). 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.
这些原则在20世纪70年代和80年代已经在Mesa、Ada、modala -2/Oberon和其他几种语言中被了解并完全实现,直到现在(在2010年代)才被应用到现代语言中,如Go(谷歌)、Swift (Apple)、c# (Microsoft)和其他几种语言中。
让我们希望这将很快成为常态,而不是例外。要实现这一目标,需要做到两件事:
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). 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).
在任何情况下,是平台推动了语言的采用,而不是相反。
引用:
[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.
其他回答
围棋的设计就是要快,这一点已经体现出来了。
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. 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). No overload allowed: you see a symbol, you know which method it refers to. It's trivially possible to compile Go in parallel because each package can be compiled independently.
请注意,Go并不是唯一具有这些特性的语言(模块是现代语言的标准),但它们做得很好。
编译的基本思想实际上非常简单。原则上,递归下降解析器可以以I/O限制的速度运行。代码生成基本上是一个非常简单的过程。符号表和基本类型系统并不需要大量的计算。
然而,降低编译器的速度并不难。
如果存在一个预处理器阶段,其中包含多级包含指令、宏定义和条件编译,尽管这些东西很有用,但加载它并不难。(举个例子,我想到了Windows和MFC头文件。)这就是为什么预编译头文件是必要的。
在优化生成的代码方面,可以向该阶段添加多少处理是没有限制的。
编译效率是主要的设计目标:
最后,它的目的是要快:在一台计算机上构建一个大型可执行文件最多只需要几秒钟。为了实现这些目标,需要解决一些语言问题:表达性强但轻量级的类型系统;并发性和垃圾回收;刚性依赖规范;等等。常见问题解答
关于与解析相关的特定语言特性,语言常见问题解答非常有趣:
第二,该语言被设计成易于分析,并且可以在没有符号表的情况下进行解析。
测试编译器翻译效率的一个很好的方法是自编译:给定的编译器编译自己需要多长时间?对于c++来说,这需要很长的时间(几个小时?)相比之下,在现代机器[1]上,Pascal/Modula-2/Oberon编译器将在不到一秒钟的时间内自行编译。
Go一直受到这些语言的启发,但这种效率的一些主要原因包括:
A clearly defined syntax that is mathematically sound, for efficient scanning and parsing. 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). 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.
这些原则在20世纪70年代和80年代已经在Mesa、Ada、modala -2/Oberon和其他几种语言中被了解并完全实现,直到现在(在2010年代)才被应用到现代语言中,如Go(谷歌)、Swift (Apple)、c# (Microsoft)和其他几种语言中。
让我们希望这将很快成为常态,而不是例外。要实现这一目标,需要做到两件事:
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). 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).
在任何情况下,是平台推动了语言的采用,而不是相反。
引用:
[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.
摘自Alan Donovan和Brian Kernighan所著的《the Go Programming Language》一书:
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.