¿Por qué Go es tan lento (en comparación con Java)?

109

Como pudimos ver en The Computer Language Benchmarks Game en 2010:

  • Go es en promedio 10 veces más lento que C
  • Go es 3 veces más lento que Java .

¿Cómo puede ser esto, teniendo en cuenta que el compilador Go produce código nativo para su ejecución?
¿Compiladores inmaduros para Go? ¿O hay algún problema intrínseco con el lenguaje Go?

EDITAR:
La mayoría de las respuestas niegan la lentitud intrínseca de Go languge, alegando que el problema reside en compiladores inmaduros.
Por lo tanto, hice algunas pruebas propias para calcular los números de Fibonacci : El algoritmo iterativo se ejecuta en Go (freebsd, 6g) con la samevelocidad como en C (con la opción O3). El aburrido recursivo se ejecuta en Go 2 timesmás lento que en C (con la opción -O3; con -O0 - lo mismo). Pero no he visto una caída de 10 veces como en el Benchmarks Game.

Oleg Razgulyaev
fuente
36
Para ser justos, C es ASM disfrazado, y Java tiene algunas optimizaciones serias bajo el capó en estos días.
Matthew Scharley
16
Quizás el índice de referencia tampoco refleja los puntos fuertes de Go. Puede ser que otros puntos de referencia sean más rápidos que este. Además, a menudo no es el rendimiento, sino la legibilidad del código lo que más cuenta.
extraneon
7
@extraneon: estoy de acuerdo. Recuerde, Go está diseñado para Google y Google ejecuta código de forma rutinaria en 2 millones de núcleos. El juego Benchmarks usa solo 4 núcleos, creo.
Jörg W Mittag
4
@extraneon: Estoy de acuerdo en general, pero Go fue diseñado específicamente con la velocidad en mente, como en, "los programas resultantes se ejecutan casi tan rápido como el código C o C ++ comparable".
shosti
4
Su pregunta asume demasiado: "La mayoría de las respuestas niegan la lentitud intrínseca de Go languge" es una frase incorrecta para usar en una pregunta. ¿Tiene una pregunta que hacer o una declaración que hacer? Consulte c2.com/cgi/wiki?HostileStudent para comprender su error.
Chris

Respuestas:

102

Los compiladores 6g y 8g no se optimizan particularmente, por lo que el código que producen no es particularmente rápido.

Están diseñados para ejecutarse rápidamente y producir código que está bien (hay un poco de optimización). gccgoutiliza las pasadas de optimización existentes de GCC, y podría proporcionar una comparación más significativa con C, pero gccgo aún no tiene todas las funciones.

Las cifras de referencia se refieren casi exclusivamente a la calidad de la implementación. No tienen mucho que ver con el lenguaje como tal, excepto en la medida en que la implementación gasta tiempo de ejecución en funciones de lenguaje que el banco de pruebas realmente no necesita. En la mayoría de los lenguajes compilados, un compilador lo suficientemente inteligente podría, en teoría, eliminar lo que no se necesita, pero llega un punto en el que estás manipulando la demostración, ya que muy pocos usuarios reales del lenguaje escribirían programas que no usaran esa característica. . Sacar cosas del camino sin eliminarlas por completo (por ejemplo, predecir destinos de llamadas virtuales en Java compilado con JIT) comienza a ser complicado.

FWIW, mi propia prueba muy trivial con Go cuando lo estaba viendo (un bucle de suma de enteros, básicamente), gccgo produjo código hacia el extremo rápido del rango entre gcc -O0y gcc -O2para el equivalente C. Go no es intrínsecamente lento, pero los compiladores aún no lo hacen todo. Apenas sorprendente para un idioma que tiene 10 minutos.

Steve Jessop
fuente
7
Además, es posible que los programas Go en The Computer Language Benchmarks Game no estén tan optimizados como los de C y Java.
el.pescado
¿Qué pasa entre gcc -O0 y gcc -O3? ¿Existe siquiera la intención de que los compiladores "hagan todo"?
igouy
@igouy: bueno, estoy bastante seguro de que hay una intención de que gccgo haga la recolección de basura, que actualmente no lo hace. Todavía hay algunas características para incluir en los compiladores g, por ejemplo, actualmente no usan los subprocesos de host particularmente bien (específicamente, el programador goroutine no es preventivo). Más allá de eso, no conozco los planes de Google, si los compiladores de g alguna vez se optimizarán ferozmente o si solo gccgo lo hará.
Steve Jessop
1
@xitrium: Creo que la intención de Go es que no se requiera que las implementaciones se programen en forma cooperativa, pueden adelantarse si lo desean. Consulte, por ejemplo , code.google.com/p/go/issues/detail?id=543 , que no se ha cerrado como "absurdo, corregir este supuesto error contradeciría la definición del lenguaje Go", que debería ser si Las implementaciones de Go tienen prohibido adelantarse :-) El problema se agravó por el hecho de que, por defecto, Go usaba solo un hilo de host, sin importar cuántas rutinas de gor se pudieran ejecutar.
Steve Jessop
6
La respuesta puede estar un poco desactualizada a partir de ahora. Recientemente, se lanzó la primera versión beta de Go 1.1 , afirman que el rendimiento de los programas compilados aumenta entre un 30% y un 40%. Que alguien vuelva a hacer estas pruebas.
fuz
51

En la próxima versión de las preguntas frecuentes de Go , debería aparecer algo similar a lo siguiente.

Actuación

¿Por qué Go tiene un mal desempeño en el benchmark X?

Uno de los objetivos de diseño de Go es aproximarse al rendimiento de C para programas comparables, pero en algunos puntos de referencia lo hace bastante mal, incluidos varios en pruebas / banco de pruebas. Los más lentos dependen de las bibliotecas para las que Go no dispone de versiones de rendimiento comparable. Por ejemplo, los pidigits dependen de un paquete matemático de precisión múltiple, y las versiones C, a diferencia de las de Go, usan GMP (que está escrito en ensamblador optimizado). Los puntos de referencia que dependen de expresiones regulares (regex-dna, por ejemplo) están comparando esencialmente el paquete provisional de expresiones regulares de Go con bibliotecas de expresiones regulares maduras y altamente optimizadas como PCRE.

Los juegos de referencia se ganan con un ajuste exhaustivo y las versiones Go de la mayoría de las pruebas necesitan atención. Si mide programas C y Go comparables (el complemento inverso es un ejemplo), verá que los dos lenguajes tienen un rendimiento en bruto mucho más cercano de lo que indicaría esta suite.

Aún así, hay margen de mejora. Los compiladores son buenos pero podrían ser mejores, muchas bibliotecas necesitan un trabajo de rendimiento importante y el recolector de basura aún no es lo suficientemente rápido (incluso si lo fuera, tener cuidado de no generar basura innecesaria puede tener un efecto enorme).

Y aquí hay algunos detalles más sobre The Computer Benchmarks Game de un hilo de lista de correo reciente.

Rendimiento y recolección de basura en gccgo (1)

Recolección de basura y rendimiento en gccgo (2)

Es importante tener en cuenta que Computer Benchmarks Game es solo un juego. Las personas con experiencia en la medición del rendimiento y la planificación de la capacidad combinan cuidadosamente las cargas de trabajo similares con cargas de trabajo reales y realistas; ellos no juegan juegos.

peterSO
fuente
1
Y aquí algunos detalles de ese mismo hilo que ha excluido: groups.google.com/group/golang-nuts/msg/2e568d2888970308
igouy
3
Es importante tener en cuenta que los "puntos de referencia son una tontería", no solo los puntos de referencia publicados como el juego de puntos de referencia, shootout.alioth.debian.org/flawed-benchmarks.php
igouy
18
(y todos ...) Claro que es un "juego" , pero cuando veo que Go es solo dos veces más lento que el más rápido en estos puntos de referencia, mi primera impresión es "guau, Go parece rápido" , porque sé que estos puntos de referencia son defectuoso. Por el contrario, cuando veo que Ruby es 65 veces más lento que el más rápido, pienso para mí mismo "no voy a usar Ruby para mi próximo esfuerzo intensivo numéricamente concurrente" . Así que puede ser un "juego", pero hay algo de verdad en él si lo tomas con un grano de sal.
Sintaxis T3rr0r
La planificación de la capacidad tiene un aspecto muy importante: el costo. Ya sea que necesite cajas X o 2 * X, al final, hace una gran diferencia. Y dado que nadie puede estimar qué se ejecutará en el futuro con ellos, la mejor opción es echar un vistazo a las diferentes cargas de trabajo. Revisé algunas implementaciones de estos y encontré que en su mayoría estaban bien. Creo que los resultados se pueden utilizar como base para las estimaciones.
Agoston Horvath
Generalmente, los sistemas del mundo real están limitados por IO, no por CPU. Por lo tanto, si Go es 2x o 5x es más lento, difícilmente marca una diferencia en la planificación de la capacidad, como la conmutación por error, el equilibrio de carga, el almacenamiento en caché, la topología de la base de datos y similares. Es por eso que las aplicaciones a la escala de YouTube pueden permitirse ejecutar muchos de sus sistemas en Python.
Sujoy Gupta
34

Mi respuesta no es tan técnica como la de los demás, pero creo que sigue siendo relevante. Vi los mismos puntos de referencia en el juego Computer Benchmarks cuando decidí empezar a aprender Go. Pero honestamente creo que todos estos puntos de referencia sintéticos son inútiles en términos de decidir si Go es lo suficientemente rápido para ti.

Recientemente había escrito un servidor de mensajes en Python usando Tornado + TornadIO + ZMQ, y para mi primer proyecto de Go decidí reescribir el servidor en Go. Hasta ahora, habiendo conseguido que el servidor tenga la misma funcionalidad que la versión de Python, mis pruebas me muestran un aumento de velocidad de 4.7x en el programa Go. Eso sí, solo he estado codificando en Go durante tal vez una semana, y he estado codificando en Python durante más de 5 años.

Go solo se volverá más rápido a medida que continúen trabajando en él, y creo que realmente se reduce a cómo funciona en una aplicación del mundo real y no en pequeños puntos de referencia computacionales. Para mí, Go aparentemente resultó en un programa más eficiente que el que podía producir en Python. Esa es mi opinión sobre la respuesta a esta pregunta.

jdi
fuente
3
¿Cuánto más lento crees que escribirás código Go que Python?
Erik Engheim
7
@AdamSmith - Diría que escribiría código Go más lentamente que Python solo porque he estado codificando Python durante más de 7 años y solo un poco de Go. Pero en términos de Go frente a otros lenguajes compilados de tipo estático, apuesto a que escribiría Go más rápido que otros. Personalmente, siento que es lo más parecido a la simplicidad de Python con velocidad entre C y C ++
jdi
5
Tengo una historia similar. Acabo de empezar a aprender Go y, según Benchmarks Game, Go es MÁS LENTO que JavaScript V8. Resulta que mi programa que es intenso en operaciones binarias se ejecuta 10 veces más rápido con código Go no optimizado que en una VM V8 altamente optimizada. Go puede ser más lento que C en muchas operaciones, sin embargo, nadie está escribiendo sitios web en C. Go ya es una opción perfectamente viable, y solo debería mejorar a medida que aparezcan nuevas bibliotecas, marcos y herramientas.
si __nombre__ es Ninguno
1
@ user962247 esta es una declaración general falsa y loca. Llevo años escribiendo Go y es increíblemente rápido. Nadie afirma que superará a C / C ++ / Java en todos los puntos de referencia sintéticos posibles. Pero gana en algunos (consulte el sitio de juegos de referencia). Tómelo de alguien que ha estado escribiendo código Go de producción durante años. Es rápido y productivo.
jdi
6

Las cosas han cambiado.

Creo que la respuesta correcta actual a su pregunta es refutar la noción de que ir es lento. En el momento de su consulta, su juicio estaba justificado, pero desde entonces go ha ganado mucho terreno en términos de rendimiento. Ahora, todavía no es tan rápido como C, pero no está cerca de ser 10 veces más lento, en un sentido general.

Juego de benchmarks de lenguaje informático

En el momento de escribir este artículo:

source  secs    KB      gz      cpu     cpu load

reverse-complement
1.167x
Go      0.49    88,320  1278    0.84    30% 28% 98% 34%
C gcc   0.42    145,900 812     0.57    0% 26% 20% 100%

pidigits
1.21x
Go      2.10    8,084   603 2.10    0% 100% 1% 1%
C gcc   1.73    1,992   448 1.73    1% 100% 1% 0%

fasta
1.45x
Go      1.97    3,456   1344    5.76    76% 71% 74% 73%
C gcc   1.36    2,800   1993    5.26    96% 97% 100% 97%

regex-dna
1.64x
Go      3.89    369,380 1229    8.29    43% 53% 61% 82%
C gcc   2.43    339,000 2579    5.68    46% 70% 51% 72%

fannkuch-redux
1.72x
Go      15.59   952 900 62.08   100% 100% 100% 100%
C gcc   9.07    1,576   910 35.43   100% 99% 98% 94%

spectral-norm
2x
Go      3.96    2,412   548 15.73   99% 99% 100% 99%
C gcc   1.98    1,776   1139    7.87    99% 99% 100% 99%

n-body
2.27x
Go      21.73   952 1310    21.73   0% 100% 1% 2%
C gcc   9.56    1,000   1490    9.56    1% 100% 1% 1%

k-nucleotide
2.40x
Go      15.48   149,276 1582    54.68   88% 97% 90% 79%
C gcc   6.46    130,076 1500    17.06   51% 37% 89% 88%

mandelbrot
3.19x
Go      5.68    30,756  894 22.56   100% 100% 99% 99%
C gcc   1.78    29,792  911 7.03    100% 99% 99% 98%

Sin embargo, sufre brutalmente en el punto de referencia del árbol binario:

binary-trees
12.16x
Go      39.88   361,208 688 152.12  96% 95% 96% 96%
C gcc   3.28    156,780 906 10.12   91% 77% 59% 83%
tiffon
fuente
Ahora está a la par con Java, pero ¿no se creó Go explícitamente para ser más rápido que Java, mientras se usaba para las mismas cosas (aplicaciones de red del lado del servidor)?
MaxB
1
@MaxB no, no fue creado con el objetivo de ser más rápido que Java. Fue creado con el objetivo de tener un buen rendimiento, una compilación más rápida que C ++ y una concurrencia nativa más fácil para permitir que los desarrolladores sean más productivos. Superar la velocidad de ejecución de otros idiomas no fue un factor determinante.
jdi
5

A pesar de la no tan buena eficiencia de Go sobre el uso de ciclos de CPU, el modelo de concurrencia de Go es mucho más rápido que el modelo de subprocesos en Java, por ejemplo, y puede ser comparable al modelo de subprocesos de C ++.

Tenga en cuenta que en el banco de pruebas de anillo de hilo , Go fue 16 veces más rápido que Java. En el mismo escenario, Go CSP era casi comparable a C ++, pero usaba 4 veces menos memoria.

El gran poder del lenguaje Go es su modelo de concurrencia, Communicating Sequential Processes, CSP, especificado por Tony Hoare en los años 70, que es fácil de implementar y se ajusta a necesidades altamente concurrentes.

DLopes
fuente
2

Hay dos razones básicas por las que Java es más rápido que Go y C ++, y puede ser más rápido que C en muchos casos:

1) El compilador JIT. Puede en línea llamadas a funciones virtuales a través de múltiples niveles, incluso con clases OO, según el perfil de tiempo de ejecución. Esto no es posible en un lenguaje compilado estáticamente (aunque la recopilación más reciente basada en el perfil grabado puede ayudar). Esto es muy importante para la mayoría de los puntos de referencia que involucran algoritmos repetitivos.

2) El GC. La asignación de memoria basada en GC es casi gratuita, en comparación con malloc. Y la penalización "gratuita" se puede amortizar durante todo el tiempo de ejecución; a menudo se omite porque el programa finaliza antes de que sea necesario recolectar toda la basura.

Hay cientos (¿miles?) De desarrolladores extremadamente talentosos que hacen que GC / JVM sea eficiente. Pensar que puede "codificar mejor que todos ellos" es una locura. Es un problema del ego humano en el fondo: los humanos tienen dificultades para aceptar que con el entrenamiento adecuado de humanos talentosos, la computadora funcionará mejor que los humanos que la programaron.

Por cierto, C ++ puede ser tan rápido como C si no usa y de las características de OO, pero entonces está bastante cerca de programar en C para empezar.

Más importante aún, las "diferencias de velocidad" en estas pruebas generalmente no tienen sentido. Los costos de IO son órdenes de magnitud más que las diferencias de rendimiento, por lo que los diseños adecuados que minimizan los costos de IO siempre ganan, incluso en un lenguaje interpretado. Muy pocos sistemas están vinculados a la CPU.

Como nota final, la gente se refiere al "juego de evaluaciones comparativas del lenguaje informático" como una "medida científica". Las pruebas son completamente defectuosas, por ejemplo, si ve las pruebas de Java para nbody. Cuando ejecuto las pruebas en el mismo sistema operativo / hardware, obtengo aproximadamente 7,6 segundos para Java y 4,7 segundos para C, lo cual es razonable, no la lentitud 4x que informan las pruebas. Es un cebo de clics, una noticia falsa, diseñada para generar tráfico en el sitio.

Como nota final, final ... Ejecuté las pruebas usando Go, y fueron 7,9 segundos. El hecho de que cuando haga clic en Ir, lo compare con Java, y cuando haga clic en Java lo compare con C, debería ser una señal de alerta para cualquier ingeniero serio.

Para una comparación del mundo real de Java, Go y C ++, consulte https://www.biorxiv.org/content/10.1101/558056v1 alerta de spoiler, Java se destaca en rendimiento bruto, con Go a la cabeza con uso combinado de memoria y tiempo de pared.

robert engels
fuente
incorrecto. C ++ ES tan rápido como C, especialmente cuando usa OOP, ese es su certificado de nacimiento. más abstracción (como en las clases) SIN NINGUNA DEGRADACIÓN DE RENDIMIENTO EN TIEMPO DE EJECUCIÓN, CON CERO MEMORIA EXTRA BYTES. si no lo sabe, siga jugando con java, c #, go, python, etcétera
// Por cierto, C ++ puede ser tan rápido como C si no usa y de las características de OO //, pero entonces está bastante cerca de programar en C // para empezar. si dices eso, tienes muy pocas pistas sobre c ++, por tu propio bien, no lo uses. c y c ++ odian la magia y las mentes medievales, supersticiosas por naturaleza, como oh, escuché eso, léelo en Internet, debe ser verdad ... mantente alejado de c y c ++, te devolverán un byte mi amigo (consejo honesto)
c es el antepasado de c ++. mucha gente todavía lo usa ... c ++ es un mejor c, donde puede hacer más sin pagar el precio. los autores de java, c # y go no lo entendieron, bueno, por supuesto que sí, pero ¿qué pueden hacer al respecto? lo mismo acerca de ser compatible con el código (c) existente. océanos de la vida real de código c! Python es un buen juguete, disfrútalo, desearía que lo hicieran bien, pero no, zen de Python debería haber comenzado con "el compilador es tu amigo" ...
>> muestra la utilización de la CPU al 30% para el programa Java << No —— "1% 0% 0% 100%".
igouy
1
@igouy Admito que ese es un error que probablemente cometí: cuando vi la carga, estaba interpretando en términos de 'carga del sistema', y asumiendo, usuario / sistema / io / inactivo, mi error, y fue sustancial.
Robert Engels
1

Creo que un hecho que a menudo se pasa por alto es que la compilación JIT puede ser> compilación estática, especialmente para funciones o métodos enlazados en tiempo de ejecución. El hotspot JIT decide en RUNTIME qué métodos incorporar, incluso puede ajustar el diseño de los datos al tamaño / arquitectura de la memoria caché de la CPU en la que se está ejecutando actualmente. C / C ++ en general puede compensar (y en general seguirá funcionando mejor) al tener acceso directo al hardware. Para Go, las cosas pueden verse diferentes ya que son de más alto nivel en comparación con C, pero actualmente carece de un sistema / compilador de optimización en tiempo de ejecución. Mi instinto me dice, Go podría ser más rápido que Java, ya que Go no exige tanto la persecución de punteros y fomenta una mejor estructura de datos, la localidad + requiere menos asignación.

R.Moeller
fuente
1

De hecho, Go no solo es elegante y eficiente en el momento del diseño, sino que también tiene un excelente rendimiento en el momento de la ejecución. La clave es utilizar el sistema operativo correcto, es decir, LINUX. Los resultados del perfil de rendimiento en Windows y Mac OS son, a falta de una palabra mejor, uno o dos órdenes de magnitud inferiores.

Dan Marinescu
fuente
0

bajo linux, el tiempo de ejecución de go es súper rápido, perfectamente comparable con c / c ++. el tiempo de ejecución de go bajo Windows y Unix no están en la misma liga

la comparación con java no es tan importante, go es tanto para el desarrollo de sistemas como de aplicaciones (ya que java es más parecido al de cuello azul para el desarrollo de aplicaciones únicamente). no entrará en detalles, pero cuando cosas como kubernetes están escritas en go, se dará cuenta de que no es un juguete amigable para consultores empresariales

No recuerdo que Google mencionó ni una sola vez el compromiso al que se refiere. go está bien diseñado, simple, elegante y eficiente para diseñar programas de nivel de aplicación y sistema, tiene punteros, asignación de memoria eficiente y desasignación, evita complicaciones derivadas de una herencia de implementación tan fácil de perder, brindándole co-rutinas y otras modernas formas de escribir aplicaciones de alto rendimiento en tiempo y presupuesto. de nuevo, go es súper rápido en Linux, que es exactamente para lo que fue diseñado (muy feliz de que lo haga)

Dan Marinescu
fuente
-4

Tanto Java como C son más explícitos con sus definiciones de datos y métodos (funciones). C tiene un tipo estático, y Java lo es menos con su modelo de herencia. Esto significa que la forma en que se manejarán los datos está bastante definida durante la compilación.

Go es más implícito con sus datos y definiciones de funciones. Las funciones integradas son de naturaleza más general y la falta de una jerarquía de tipos (como Java o C ++) le da a Go una desventaja de velocidad.

Tenga en cuenta que el objetivo de Google para el lenguaje Go es tener un compromiso aceptable entre la velocidad de ejecución y la velocidad de codificación. Creo que están alcanzando un buen punto óptimo en su primer intento, y las cosas solo mejorarán a medida que se haga más trabajo.

Si compara Go con lenguajes de escritura más dinámica cuya principal ventaja es la velocidad de codificación, verá la ventaja de velocidad de ejecución de Go. Go es 8 veces más rápido que perl y 6 veces más rápido que Ruby 1.9 y Python 3 en los puntos de referencia que usó.

De todos modos, la mejor pregunta para hacer es Go, ¿un buen compromiso entre la facilidad de programación y la velocidad de ejecución? Mi respuesta es sí y debería mejorar.

Bill C
fuente
20
"la falta de una jerarquía de tipos (como Java o C ++) le da a Go una desventaja de velocidad" —wut?
Erik Kaplun
6
"Go es más implícito con sus datos y definiciones de funciones". Incorrecto. ¿Te refieres a cómo los tipos pueden implementar métodos sin ser explícitos al respecto? El compilador detecta la pertenencia a una interfaz de tipo. Esto es rápido "Las funciones integradas son de naturaleza más general" no, las funciones integradas están, como todo lo demás, compiladas. Lo mismo sucede con las plantillas de C ++. "la falta de una jerarquía de tipos (como Java o C ++) le da a Go una desventaja de velocidad" - incorrecto, una jerarquía de tipos no tiene nada que ver con la ejecución en tiempo de ejecución.
Malcolm