¿Cómo va a compilar tan rápido?


He buscado en Google y hurgado en el sitio web de Go, pero parece que no puedo encontrar una explicación para los extraordinarios tiempos de compilación de Go. ¿Son productos de las características del lenguaje (o la falta de ellas), un compilador altamente optimizado, o algo más? No estoy tratando de promocionar a Go, solo tengo curiosidad.

Author: Evan Kroske, 2010-06-04

11 answers

Análisis de dependencias.

Desde el Ir FAQ :

Go proporciona un modelo para el software construcción que hace dependencia análisis fácil y evita gran parte de la sobrecarga de archivos de inclusión de estilo C y biblioteca.

Esa es la razón principal de la compilación rápida. Y esto es por diseño.

 168
Author: Igor Krivokon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-26 05:46:07

Creo que no es que los compiladores Go sean rápidos, es que otros compiladores son lentos.

Los compiladores de C y C++ tienen que analizar enormes cantidades de encabezados - por ejemplo, compilar C++ "hello world" requiere compilar líneas de código de 18k, ¡lo que es casi medio megabyte de fuentes!

$ cpp hello.cpp | wc
  18364   40513  433334

Los compiladores Java y C# se ejecutan en una VM, lo que significa que antes de que puedan compilar nada, el sistema operativo tiene que cargar toda la VM, luego tienen que ser compilados desde JIT bytecode a código nativo, todo lo cual lleva algún tiempo.

La velocidad de compilación depende de varios factores.

Algunos lenguajes están diseñados para ser compilados rápidamente. Por ejemplo, Pascal fue diseñado para ser compilado usando un compilador de una sola pasada.

Los compiladores también se pueden optimizar. Por ejemplo, el compilador Turbo Pascal fue escrito en ensamblador optimizado a mano, lo que, combinado con el diseño del lenguaje, resultó en un compilador realmente rápido trabajando en hardware de clase 286. Creo que que incluso ahora, los compiladores Pascal modernos (por ejemplo, FreePascal) son más rápidos que los compiladores Go.

 68
Author: el.pescado,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-30 09:07:15

La eficiencia de la compilación fue uno de los principales objetivos del diseño:

Finalmente, se pretende que sea rápido: debería tomar como máximo unos segundos para construir un ejecutable grande en un solo equipo. Para cumplir con estos objetivos se requería abordar una serie de problemas lingüísticos: un sistema de tipos expresivo pero ligero; concurrencia y recolección de basura; especificación de dependencia rígida; y así sucesivamente. FAQ

Las preguntas frecuentes sobre el idioma son bastante interesantes en lo que respecta al idioma específico características relacionadas con el análisis:

En segundo lugar, el lenguaje ha sido diseñado para ser fácil de analizar y se puede analizar sin una tabla de símbolos.

 32
Author: Larry OBrien,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-29 18:39:04

Hay múltiples razones por las que el compilador Go es mucho más rápido que la mayoría de los compiladores de C/C++:

  • Razón principal : La mayoría de los compiladores de C/C++ exhiben diseños excepcionalmente malos (desde la perspectiva de la velocidad de compilación). Además, desde la perspectiva de la velocidad de compilación, algunas partes del ecosistema de C/C++ (como los editores en los que los programadores escriben sus códigos) no están diseñadas teniendo en cuenta la velocidad de compilación.

  • Razón principal : La velocidad de compilación rápida era una elección consciente en el compilador Go y también en el lenguaje Go

  • El compilador Go tiene un optimizador más simple que los compiladores C / C++

  • A diferencia de C++, Go no tiene plantillas ni funciones en línea. Esto significa que Go no necesita realizar ninguna plantilla o instanciación de función.

  • El compilador Go genera código de ensamblado de bajo nivel antes y el optimizador trabaja en el código de ensamblado, mientras que en un compilador típico de C/C++ la optimización pasa a trabajar en un representación interna del código fuente original. La sobrecarga adicional en el compilador de C/C++ proviene del hecho de que la representación interna necesita ser generada.

  • El enlace final (5l / 6l / 8l) de un programa Go puede ser más lento que enlazar un programa C / C++, porque el compilador Go está pasando por todo el código ensamblador utilizado y tal vez también está haciendo otras acciones adicionales que los enlazadores de C/C++ no están haciendo

  • Algunos compiladores de C / C++ (GCC) generan instrucciones en forma de texto (que se pasa al ensamblador), mientras que el compilador Go genera instrucciones en forma binaria. Se necesita trabajo extra (pero no mucho) para transformar el texto en binario.

  • El compilador Go se dirige solo a un pequeño número de arquitecturas de CPU, mientras que el compilador GCC se dirige a un gran número de CPU

  • Los compiladores que fueron diseñados con el objetivo de una alta velocidad de compilación, como Jikes, son rápidos. En una CPU de 2GHz, Jikes puede compilar más de 20000 líneas de Código Java por segundo (y el modo incremental de compilación es aún más eficiente).

 28
Author: user811773,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-29 21:07:01

Si bien la mayor parte de lo anterior es cierto, hay un punto muy importante que no se mencionó realmente: La administración de dependencias.

Go solo necesita incluir los paquetes que está importando directamente (como aquellos ya importados lo que necesitan). Esto está en marcado contraste con C / C++, donde cada archivo comienza a incluir encabezados x, que incluyen encabezados y, etc. En pocas palabras: La compilación de Go toma tiempo lineal w.r.t para el número de paquetes importados, donde C / C++ toma tiempo exponencial.

 21
Author: Kosta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-08 14:09:02

Una buena prueba para la eficiencia de traducción de un compilador es la autocompilación: ¿cuánto tiempo le toma a un compilador determinado compilarse a sí mismo? Para C++ lleva mucho tiempo (¿horas?). En comparación, un compilador Pascal/Modula-2/Oberon se compilaría en menos de un segundo en una máquina moderna [1].

Go se ha inspirado en estos lenguajes, pero algunas de las principales razones de esta eficiencia incluyen:

  1. Una sintaxis claramente definida que es matemáticamente sonido, para un escaneo y análisis eficientes.

  2. Un lenguaje seguro de tipos y compilado estáticamente que usa compilación separada con verificación de dependencias y tipos a través de los límites de los módulos, para evitar la relectura innecesaria de archivos de encabezado y la recompilación de otros módulos, a diferencia de la compilación independiente como en C / C++ , donde el compilador no realiza tales comprobaciones de módulo cruzado (de ahí la necesidad de volver a leer todos una vez más, incluso para un simple programa de "hola mundo" de una sola línea).

  3. Una implementación de compilador eficiente ( por ejemplo, un solo paso, análisis recursivo de descenso de arriba hacia abajo) - que por supuesto es muy ayudado por los puntos 1 y 2 anteriores.

Estos principios ya han sido conocidos y completamente implementados en las décadas de 1970 y 1980 en idiomas como Mesa, Ada, Modula-2 / Oberon y varios otros, y solo ahora (en la década de 2010) están encontrando su camino en idiomas modernos como Go (Google), Swift (Apple), C# (Microsoft) y varios otros.

Esperemos que esto pronto sea la norma y no la excepción. Para llegar allí, dos cosas tienen que suceder:

  1. En primer lugar, los proveedores de plataformas de software como Google, Microsoft y Apple deben comenzar alentando a los desarrolladores de aplicaciones a utilizar la nueva metodología de compilación, al tiempo que les permite reutilizar su base de código existente. Esto es lo que Apple está tratando de hacer ahora con la programación Swift lenguaje, que puede coexistir con Objective-C (ya que utiliza el mismo entorno de tiempo de ejecución).

  2. En segundo lugar, las propias plataformas de software subyacentes deberían reescribirse con el tiempo utilizando estos principios, mientras que al mismo tiempo se rediseña la jerarquía de módulos en el proceso para hacerlos menos monolíticos. Esto es, por supuesto, una tarea gigantesca y bien puede tomar la mayor parte de una década (si son lo suficientemente valientes como para hacerlo realmente - que no estoy del todo seguro en el caso de Google).

En cualquier caso, es la plataforma la que impulsa la adopción del lenguaje, y no al revés.

Referencias:

[1] http://www.inf.ethz.ch/personal/wirth/ProjectOberon/PO.System.pdf , página 6: "El compilador se compila en unos 3 segundos". Esta cotización es para una placa de desarrollo FPGA Xilinx Spartan-3 de bajo costo que se ejecuta a una frecuencia de reloj de 25 MHz y cuenta con 1 MByte de memoria principal. A partir de este se puede fácilmente extrapolar a "menos de 1 segundo" para un procesador moderno que se ejecuta a una frecuencia de reloj muy superior a 1 GHz y varios GBytes de memoria principal (es decir, varios órdenes de magnitud más potentes que la placa FPGA Xilinx Spartan-3), incluso cuando se tienen en cuenta las velocidades de E/S. Ya en 1990, cuando Oberon se ejecuta en un 25MHz NS32X32 procesador con 2-4 MBytes de memoria principal, el compilador compila sí mismo en tan sólo unos segundos. La noción de realmente esperando que el compilador termine un el ciclo de compilación era completamente desconocido para los programadores de Oberon incluso en ese entonces. Para los programas típicos, siempre tomó más tiempo quitar el dedo del botón del ratón que activó el comando compile que esperar a que el compilador completara la compilación que acaba de activarse. Fue realmente una gratificación instantánea, con tiempos de espera casi cero. Y la calidad del código producido, aunque no siempre a la par con los mejores compiladores disponibles en ese entonces, fue notablemente buena para la mayoría de las tareas y bastante aceptable en general.

 18
Author: Andreas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-25 11:47:17

Go fue diseñado para ser rápido, y se nota.

  1. Gestión de dependencias: sin archivo de cabecera, solo tiene que mirar los paquetes que se importan directamente (sin necesidad de preocuparse por lo que importan), por lo que tiene dependencias lineales.
  2. Gramática: la gramática de la lengua es simple, por lo que se analiza fácilmente. Aunque el número de características se reduce, por lo tanto el código del compilador en sí es apretado (pocas rutas).
  3. No se permite sobrecarga: ves un símbolo, sabes qué método referir.
  4. Es trivialmente posible compilar Go en paralelo porque cada paquete se puede compilar de forma independiente.

Tenga en cuenta que GO no es el único lenguaje con tales características (los módulos son la norma en los idiomas modernos), pero lo hicieron bien.

 10
Author: Matthieu M.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-10 15:52:10

La idea básica de compilación es en realidad muy simple. Un analizador de descenso recursivo, en principio, puede funcionar a velocidad de enlace de E / S. La generación de código es básicamente un proceso muy simple. Una tabla de símbolos y un sistema de tipos básicos no es algo que requiera mucho cómputo.

Sin embargo, no es difícil ralentizar un compilador.

Si hay una fase de preprocesador, con múltiples niveles include directivas, definiciones de macro y compilación condicional, tan útiles como las las cosas son, no es difícil cargarlo. (Por ejemplo, estoy pensando en los archivos de encabezado de Windows y MFC.) Es por eso que los encabezados precompilados son necesarios.

En términos de optimización del código generado, no hay límite para la cantidad de procesamiento que se puede agregar a esa fase.

 8
Author: Mike Dunlavey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-04 20:24:29

Simplemente ( en mis propias palabras ), porque la sintaxis es muy fácil (analizar y analizar )

Por ejemplo, sin herencia de tipo significa, no análisis problemático para averiguar si el nuevo tipo sigue las reglas impuestas por el tipo base.

Por ejemplo en este ejemplo de código: "interfaces" el compilador no va y comprueba si el tipo deseado implementa la interfaz dada mientras analiza ese tipo. Solo hasta que se use ( y SI se usa ) el cheque se realiza.

Otro ejemplo, el compilador te dice si estás declarando una variable y no la estás usando ( o si se supone que tienes un valor devuelto y no lo estás)

Lo siguiente no compila:

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

Este tipo de implementaciones y principios hacen que el código resultante sea más seguro, y el compilador no tiene que realizar validaciones adicionales que el programador puede hacer.

En general, todos estos detalles hacen que un lenguaje sea más fácil de analizar, lo que resulta en compilaciones rápidas.

De nuevo, en mis propias palabras.

 4
Author: OscarRyz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:55:03

Creo que Go fue diseñado en paralelo con la creación del compilador, por lo que fueron mejores amigos desde su nacimiento. (OMI)

 2
Author: Andrey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-04 18:13:29

Citando del libro " El lenguaje de programación Go " de Alan Donovan y Brian Kernighan:

La compilación Go es notablemente más rápida que la mayoría de los otros lenguajes compilados, incluso cuando se construye desde cero. Hay tres razones principales para la velocidad del compilador. En primer lugar, todas las importaciones deben enumerarse explícitamente al principio de cada archivo de origen, por lo que el compilador no tiene que leer y procesar un archivo completo para determinar sus dependencias. Segundo, las dependencias de un paquete formar un gráfico acíclico dirigido, y debido a que no hay ciclos, los paquetes se pueden compilar por separado y tal vez en paralelo. Finalmente, el archivo objeto de un paquete Go compilado registra información de exportación no solo para el paquete en sí, sino también para sus dependencias. Al compilar un paquete, el compilador debe leer un archivo objeto para cada importación, pero no necesita mirar más allá de estos archivos.

 2
Author: Miscreant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-16 18:05:43