Pourquoi Go est-il si lent (par rapport à Java)?

109

Comme nous avons pu le voir dans The Computer Language Benchmarks Game en 2010:

  • Go est en moyenne 10 fois plus lent que C
  • Go est 3 fois plus lent que Java !?

Comment est-ce possible, sachant que le compilateur Go produit du code natif pour l'exécution?
Des compilateurs immatures pour Go? Ou il y a un problème intrinsèque avec le langage Go?

EDIT:
La plupart des réponses nient la lenteur intrinsèque de Go languge, affirmant que le problème réside dans des compilateurs immatures.
Par conséquent, j'ai fait quelques tests pour calculer les nombres de Fibonacci : l'algorithme itératif s'exécute en Go (freebsd, 6g) avec la samevitesse comme en C (avec l'option O3). Le récursif terne s'exécute en Go 2 timesplus lentement qu'en C (avec l'option -O3; avec -O0 - la même chose). Mais je n'ai pas vu une baisse de 10x comme dans le jeu Benchmarks.

Oleg Razgulyaev
la source
36
Pour être juste, C est ASM déguisé, et Java a de sérieuses optimisations sous le capot ces jours-ci.
Matthew Scharley
16
Peut-être que la référence ne reflète pas non plus les atouts de Go. Il se peut que d'autres repères soient en fait plus rapides que cela. D'ailleurs, souvent ce ne sont pas les performances mais la lisibilité du code qui compte le plus.
extraneon le
7
@extraneon: Je suis d'accord. N'oubliez pas que Go est conçu pour Google et Google exécute régulièrement du code sur 2 millions de cœurs. Le jeu Benchmarks n'utilise que 4 cœurs, je crois.
Jörg W Mittag
4
@extraneon: Je suis d'accord en général, mais Go a été spécialement conçu avec la vitesse à l'esprit, comme dans «les programmes résultants s'exécutent presque aussi rapidement que du code C ou C ++ comparable».
shosti
4
Votre question en suppose trop: «La plupart des réponses nient la lenteur intrinsèque de Go languge» est une expression incorrecte à utiliser dans une question. Avez-vous une question à poser ou une déclaration à faire? Veuillez consulter c2.com/cgi/wiki?HostileStudent pour comprendre votre erreur.
Chris

Réponses:

102

Les compilateurs 6g et 8g ne sont pas particulièrement optimisés, donc le code qu'ils produisent n'est pas particulièrement rapide.

Ils sont conçus pour fonctionner rapidement eux-mêmes et produire du code qui convient (il y a un peu d'optimisation). gccgoutilise les passes d'optimisation existantes de GCC, et pourrait fournir une comparaison plus précise avec C, mais gccgo n'est pas encore complet.

Les chiffres de référence concernent presque entièrement la qualité de la mise en œuvre. Ils n'ont pas beaucoup à voir avec le langage en tant que tel, sauf dans la mesure où l'implémentation passe le temps d'exécution à prendre en charge des fonctionnalités de langage dont le benchmark n'a pas vraiment besoin. Dans la plupart des langages compilés, un compilateur suffisamment intelligent pourrait en théorie supprimer ce qui n'est pas nécessaire, mais il arrive un moment où vous truquez la démo, car très peu de vrais utilisateurs du langage écriraient des programmes qui n'utilisent pas cette fonctionnalité. . Déplacer les choses sans les supprimer complètement (par exemple, prédire les destinations d'appels virtuels dans Java compilé JIT) commence à devenir délicat.

FWIW, mon propre test très trivial avec Go quand je le regardais (une boucle d'addition d'entiers, en gros), gccgo a produit du code vers l'extrémité rapide de la plage entre gcc -O0et gcc -O2pour l'équivalent C. Go n'est pas intrinsèquement lent, mais les compilateurs ne font pas encore tout. Pas étonnant pour une langue vieille de 10 minutes.

Steve Jessop
la source
7
De plus, il se peut que les programmes Go dans The Computer Language Benchmarks Game ne soient pas aussi optimisés que ceux en C et Java.
el.pescado
Qu'en est-il entre gcc -O0 et gcc -O3? Y a-t-il même l'intention que les compilateurs «fassent tout»?
igouy
@igouy: eh bien, je suis presque sûr qu'il y a une intention que gccgo fasse le ramasse-miettes, ce qui n'est pas le cas actuellement. Il y a encore des fonctionnalités à intégrer dans les compilateurs g, par exemple, ils n'utilisent actuellement pas particulièrement bien les threads hôtes (en particulier, le programmateur goroutine n'est pas préemptif). Au-delà de cela, je ne connais pas les plans de Google, si les compilateurs g s'optimiseront un jour férocement, ou si seulement gccgo le fera.
Steve Jessop
1
@xitrium: Je pense que l'intention de Go est que les implémentations ne devraient pas être obligées de planifier en coopération, elles peuvent anticiper si elles le souhaitent. Voir par exemple code.google.com/p/go/issues/detail?id=543 , qui n'a pas été fermé comme "absurde, corriger ce soi-disant bogue serait en contradiction avec la définition du langage Go", ce qu'il devrait être si Il est interdit de préempter les implémentations de Go :-) Le problème était aggravé par le fait que, par défaut, Go n'utilisait qu'un seul thread hôte, quel que soit le nombre de goroutines exécutables.
Steve Jessop
6
La réponse est peut-être un peu dépassée pour le moment. Récemment, la première version bêta de Go 1.1 a été publiée , ils affirment que les performances des programmes compilés augmentent d'environ 30% à 40%. Quelqu'un, s'il vous plaît, refaites ces tests.
fuz le
51

Dans la prochaine version de la FAQ Go , quelque chose de similaire à ce qui suit devrait apparaître.

Performance

Pourquoi Go fonctionne-t-il mal sur le benchmark X?

L'un des objectifs de conception de Go est d'approcher les performances de C pour des programmes comparables, mais sur certains points de référence, il fait assez mal, y compris plusieurs en test / banc. Les plus lentes dépendent des bibliothèques pour lesquelles des versions de performances comparables ne sont pas disponibles dans Go. Par exemple, pidigits dépend d'un package mathématique multi-précision, et les versions C, contrairement à Go, utilisent GMP (qui est écrit en assembleur optimisé). Les benchmarks qui dépendent d'expressions régulières (regex-dna, par exemple) comparent essentiellement le package de regexp stopgap de Go à des bibliothèques d'expressions régulières matures et hautement optimisées comme PCRE.

Les jeux de référence sont gagnés par des réglages approfondis et les versions Go de la plupart des benchmarks nécessitent une attention particulière. Si vous mesurez des programmes C et Go comparables (le complément inverse en est un exemple), vous verrez que les deux langages sont beaucoup plus proches en termes de performances brutes que cette suite ne l'indiquerait.

Pourtant, il y a place à amélioration. Les compilateurs sont bons mais pourraient être meilleurs, de nombreuses bibliothèques nécessitent un travail de performance majeur et le ramasse-miettes n'est pas encore assez rapide (même si c'était le cas, prendre soin de ne pas générer de déchets inutiles peut avoir un effet énorme).

Et voici quelques détails supplémentaires sur The Computer Benchmarks Game à partir d'un fil de discussion récent sur la liste de diffusion.

Garbage collection et performances dans gccgo (1)

Garbage collection et performances dans gccgo (2)

Il est important de noter que le Computer Benchmarks Game n'est qu'un jeu. Les personnes ayant une expérience de la mesure du rendement et de la planification de la capacité correspondent soigneusement à des charges de travail réalistes et réelles; ils ne jouent pas à des jeux.

peterSO
la source
1
Et voici quelques détails de ce même fil que vous avez exclu - groups.google.com/group/golang-nuts/msg/2e568d2888970308
igouy
3
Il est important de noter que "les benchmarks sont un crock" - pas seulement les benchmarks publiés dans le jeu des benchmarks - shootout.alioth.debian.org/flawed-benchmarks.php
igouy
18
(et tout le monde ...) Bien sûr, c'est un "jeu" , mais quand je vois que Go est seulement deux fois plus lent que le plus rapide sur ces benchmarks, ma première impression est "wow, Go semble rapide" , car je sais que ces benchmarks sont défectueux. Au contraire, quand je vois que Ruby est 65 fois plus lent que le plus rapide, je me dis " je ne vais pas utiliser Ruby pour mon prochain effort concomitant-numériquement intensif" . Donc c'est peut-être un "jeu", mais il y a du vrai si vous le prenez avec un grain de sel.
SyntaxeT3rr0r
La planification des capacités a un aspect très important: le coût. Que vous ayez besoin de boîtes X ou de 2 * X fait une énorme différence à la fin. Et comme personne ne peut estimer exactement ce qui va fonctionner à l'avenir sur ceux-ci, le mieux est de jeter un coup d'œil aux différentes charges de travail. J'ai vérifié quelques implémentations de ceux-ci et les ai trouvés pour la plupart OK. Je pense que les résultats peuvent être utilisés comme base d'estimation.
Agoston Horvath
Généralement, les systèmes du monde réel sont contraints par les E / S et non par le CPU. Par conséquent, le fait que Go soit 2x ou 5x soit plus lent ne fait guère de différence pour la planification de la capacité que le basculement, l'équilibrage de charge, la mise en cache, la topologie de la base de données, etc. C'est pourquoi les applications à l'échelle de YouTube peuvent se permettre d'exécuter plusieurs de leurs systèmes en Python.
Sujoy Gupta le
34

Ma réponse n'est pas aussi technique que celle de tout le monde, mais je pense qu'elle est toujours d'actualité. J'ai vu les mêmes repères sur le Computer Benchmarks Game lorsque j'ai décidé de commencer à apprendre le Go. Mais je pense honnêtement que tous ces benchmarks synthétiques sont inutiles pour décider si Go est assez rapide pour vous.

J'avais récemment écrit un serveur de messages en Python en utilisant Tornado + TornadIO + ZMQ, et pour mon premier projet Go, j'ai décidé de réécrire le serveur en Go. Jusqu'à présent, après avoir donné au serveur les mêmes fonctionnalités que la version Python, mes tests me montrent une augmentation de vitesse d'environ 4,7 fois dans le programme Go. Remarquez que je ne codifie en Go que depuis peut-être une semaine, et je code en Python depuis plus de 5 ans.

Go ne fera qu'accélérer au fur et à mesure qu'ils continueront à travailler dessus, et je pense que cela dépend vraiment de la façon dont il fonctionne dans une application du monde réel et pas de tout petits benchmarks de calcul. Pour moi, Go a apparemment abouti à un programme plus efficace que ce que je pourrais produire en Python. C'est mon point de vue sur la réponse à cette question.

jdi
la source
3
Dans quelle mesure pensez-vous écrire du code Go plus lentement que Python?
Erik Engheim
7
@AdamSmith - Je dirais que j'écrirais du code Go plus lentement que Python uniquement parce que je codifie Python depuis plus de 7 ans et seulement un peu Go. Mais en termes de Go par rapport à d'autres langages compilés à typage statique, je parie que j'écrirais Go plus vite que d'autres. Personnellement, je pense que c'est ce qui se rapproche le plus de la simplicité de Python avec une vitesse entre C et C ++
jdi
5
J'ai une histoire similaire. Je viens de commencer à apprendre Go, et selon Benchmarks Game, Go est PLUS LENT que JavaScript V8. Il s'avère que mon programme qui est intense en opérations binaires s'exécute 10 fois plus vite avec du code Go non optimisé qu'avec une VM V8 hautement optimisée. Go peut être plus lent que C dans de nombreuses opérations, mais personne n'écrit de sites Web en C. Go est déjà une option parfaitement viable et ne devrait que s'améliorer à mesure que de nouvelles bibliothèques, cadres et outils apparaissent.
si __name__ est None
1
@ user962247 c'est une fausse déclaration générale. J'écris Go depuis des années maintenant et c'est très rapide. Personne ne prétend qu'il battra C / C ++ / Java sur tous les benchmarks synthétiques possibles. Mais ça gagne sur certains (voir le site de jeu de référence). Prenez-le de quelqu'un qui a écrit du code de production Go pendant des années. C'est rapide et productif.
jdi
6

Les choses ont changé.

Je pense que la bonne réponse actuelle à votre question est de contester l'idée que la marche est lente. Au moment de votre enquête, votre jugement était justifié, mais go a depuis gagné beaucoup de terrain en termes de performances. Maintenant, ce n'est toujours pas aussi rapide que C, mais il est loin d'être 10x plus lent, dans un sens général.

Jeu de benchmarks de langage informatique

Au moment d'écrire ces lignes:

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%

Cependant, il souffre brutalement sur le benchmark de l'arbre binaire:

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
la source
Il est maintenant à égalité avec Java, mais Go n'a-t-il pas été créé explicitement pour être plus rapide que Java, tout en étant utilisé pour les mêmes choses (applications de mise en réseau côté serveur)?
MaxB
1
@MaxB non il n'a pas été créé dans le but d'être plus rapide que Java. Il a été créé dans le but d'avoir de bonnes performances, une compilation plus rapide que C ++ et une simultanéité plus facile et native pour permettre aux développeurs d'être plus productifs. Battre la vitesse d'exécution d'autres langues n'était pas un facteur déterminant.
jdi
5

Malgré la faible efficacité de Go en ce qui concerne l'utilisation des cycles du processeur, le modèle de concurrence Go est beaucoup plus rapide que le modèle de thread en Java, par exemple, et peut être comparable au modèle de thread C ++.

Notez que dans le benchmark thread-ring , Go était 16 fois plus rapide que Java. Dans le même scénario, Go CSP était presque comparable à C ++, mais en utilisant 4x moins de mémoire.

La grande puissance du langage Go est son modèle de simultanéité, Communicating Sequential Processes, CSP, spécifié par Tony Hoare dans les années 70, étant simple à implémenter et adapté à des besoins hautement concurrents.

DLopes
la source
2

Il y a deux raisons fondamentales pour lesquelles Java est plus rapide que Go et C ++, et peut être plus rapide que C dans de nombreux cas:

1) Le compilateur JIT. Il peut intégrer des appels de fonctions virtuelles via plusieurs niveaux, même avec des classes OO, en fonction du profil d'exécution. Cela n'est pas possible dans un langage compilé statiquement (bien que la recompilation plus récente basée sur le profil enregistré puisse aider). Ceci est très important pour la plupart des benchmarks qui impliquent des algorithmes répétitifs.

2) Le GC. L'allocation de mémoire basée sur GC est presque gratuite, par rapport à malloc. Et la pénalité «gratuite» peut être amortie sur tout le temps d'exécution - souvent ignorée car le programme se termine avant que tous les déchets ne doivent être collectés.

Il existe des centaines (des milliers?) De développeurs extrêmement talentueux qui rendent le GC / JVM efficace. Penser que vous pouvez «coder mieux que tous» est une folie. C'est un problème d'ego humain en son cœur - les humains ont du mal à accepter qu'avec un entraînement approprié par des humains talentueux, l'ordinateur va mieux fonctionner que les humains qui l'ont programmé.

Btw, C ++ peut être aussi rapide que C si vous n'utilisez pas et des fonctionnalités OO, mais alors vous êtes assez proche de simplement programmer en C pour commencer.

Plus important encore, les «différences de vitesse» dans ces tests n'ont généralement aucun sens. Les coûts d'E / S sont des ordres de grandeur supérieurs aux différences de performances, et les conceptions appropriées qui minimisent les coûts d'E / S gagnent toujours, même dans un langage interprété. Très peu de systèmes sont liés au processeur.

En guise de note finale, les gens se réfèrent au «jeu des repères de langage informatique» comme une «mesure scientifique». Les tests sont complètement défectueux, par exemple, si vous affichez les tests Java pour nbody. Lorsque j'exécute les tests sur le même système d'exploitation / matériel, j'obtiens environ 7,6 secondes pour Java et 4,7 secondes pour C - ce qui est raisonnable - pas la lenteur 4x des rapports de tests. Il s'agit d'appât au clic, de fausses nouvelles, conçues pour générer du trafic sur le site.

En guise de note finale, j'ai fait les tests en utilisant Go, et c'était 7,9 secondes. Le fait que lorsque vous cliquez sur Go, il le compare à Java, et lorsque vous cliquez sur Java, il le compare à C, devrait être un signal d'alarme pour tout ingénieur sérieux.

Pour une comparaison du monde réel de Java, Go et C ++, voir https://www.biorxiv.org/content/10.1101/558056v1 alerte spoiler, Java arrive en tête des performances brutes, avec Go en tête avec l'utilisation combinée de la mémoire et l'heure du mur.

Robert Engels
la source
faux. C ++ EST aussi rapide que C, surtout lorsque vous utilisez la POO, c'est son certificat de naissance pell. plus d'abstraction (comme dans les classes) SANS AUCUNE DÉGRADATION DES PERFORMANCES D'EXÉCUTION, AVEC ZÉRO DE MÉMOIRE SUPPLÉMENTAIRE. si vous ne le savez pas, continuez à jouer avec java, c #, go, python, et cetera
// Btw, C ++ peut être aussi rapide que C si vous n'utilisez pas et des fonctionnalités OO //, mais vous êtes alors assez proche de simplement programmer en C // pour commencer. si vous dites cela, vous avez très peu d'indices sur C ++, pour votre propre bien, ne l'utilisez pas. c et c ++ détestent la magie et les esprits médiévaux, de nature superstitieuse, comme oh j'ai entendu ça, lisez-le sur internet, ça doit être vrai ... restez à l'écart de c et c ++, ils vous rendront mon ami (conseil honnête)
c est l'ancêtre de c ++. beaucoup de gens l'utilisent encore ... c ++ est un meilleur c, où vous pouvez en faire plus sans en payer le prix. les auteurs java, c # et go ne l'ont pas compris, eh bien, bien sûr, ils l'ont fait, mais que peuvent-ils faire?!? il en va de même pour la compatibilité avec le code (c) existant. la vraie vie des océans de code C! python est un joli jouet, profitez-en, j'aurais aimé qu'ils aient raison, mais non, zen de python aurait dû commencer par "compiler is your friend" ...
>> indique l'utilisation du processeur à 30% pour le programme Java << Non —— "1% 0% 0% 100%".
igouy
1
@igouy Je concède que c'est une erreur que j'ai probablement commise - quand j'ai vu la charge, j'interprétais en termes de `` chargement système '', et en supposant, utilisateur / système / io / idle - mon erreur, et c'était une erreur substantielle.
robert engels
1

Je pense qu'un fait souvent négligé est que la compilation JIT peut être> une compilation statique, en particulier pour les fonctions ou méthodes à liaison tardive (à l'exécution). Le hotspot JIT décide à RUNTIME des méthodes à intégrer, il peut même ajuster la disposition des données à la taille / l'architecture du cache du processeur sur lequel il s'exécute actuellement. C / C ++ en général peut compenser (et globalement fonctionnera toujours mieux) en ayant un accès direct au matériel. Pour Go, les choses peuvent sembler différentes car il est plus haut niveau que C, mais il manque actuellement un système / compilateur d'optimisation d'exécution. Mon instinct me dit, Go pourrait être plus rapide que Java car Go n'applique pas autant la poursuite du pointeur et encourage une meilleure localisation de la structure de données + nécessite moins d'allocation.

R.Moeller
la source
1

En fait, Go est non seulement élégant et efficace au moment de la conception, mais aussi super performant au moment de l'exécution. La clé est d'utiliser le bon système d'exploitation, à savoir LINUX. Les résultats du profilage des performances sous Windows et Mac OS sont, faute de meilleur mot, d'un ou deux ordres de grandeur inférieurs.

Dan Marinescu
la source
0

sous linux, le runtime go est super rapide, parfaitement comparable avec c / c ++. le runtime go sous windows et unix ne sont pas dans la même ligue

la comparaison avec java n'est pas si importante, go est à la fois pour le développement de systèmes et d'applications (car java ressemble plus à un col bleu pour le développement d'applications uniquement). n'entrera pas dans les détails, mais lorsque des choses comme kubernetes sont écrites à la volée, vous vous rendez compte que ce n'est pas un jouet convivial pour les consultants d'entreprise

Je ne me souviens pas que Google ait mentionné une seule fois le compromis auquel vous faites référence. go est bien conçu, simple, élégant et efficace pour la conception de programmes au niveau du système et de l'application, a des pointeurs, une allocation et une désallocation de mémoire efficaces, évite les complications résultant de l'héritage d'implémentation si facile à utiliser, vous donnant des co-routines et d'autres moyens d'écrire des applications hautes performances dans les délais et le budget. encore une fois, go est super rapide sous linux, c'est exactement ce pour quoi il a été conçu (très heureux qu'il le fasse)

Dan Marinescu
la source
-4

Java et C sont plus explicites avec leurs définitions de données et de méthode (fonction). C est typé statiquement, et Java l'est moins avec son modèle d'héritage. Cela signifie que la manière dont les données seront traitées est à peu près définie lors de la compilation.

Go est plus implicite avec ses définitions de données et de fonctions. Les fonctions intégrées sont de nature plus générale et l'absence de hiérarchie de types (comme Java ou C ++) donne à Go un inconvénient de vitesse.

Gardez à l'esprit que l'objectif de Google pour le langage Go est d'avoir un compromis acceptable entre la vitesse d'exécution et la vitesse de codage. Je pense qu'ils atteignent un bon point idéal lors de leur première tentative, et les choses ne feront que s'améliorer à mesure que davantage de travail sera accompli.

Si vous comparez Go avec des langages à typage plus dynamique dont le principal avantage est la vitesse de codage, vous verrez l'avantage de la vitesse d'exécution de Go. Go est 8 fois plus rapide que perl et 6 fois plus rapide que Ruby 1.9 et Python 3 sur les benchmarks que vous avez utilisés.

Quoi qu'il en soit, la meilleure question à se poser est-elle un bon compromis entre la facilité de programmation et la vitesse d'exécution? Ma réponse est oui et ça devrait aller mieux.

Projet de loi C
la source
20
"l'absence d'une hiérarchie de types (comme Java ou C ++) donne à Go un inconvénient de vitesse" —wut?
Erik Kaplun
6
"Go est plus implicite avec ses définitions de données et de fonctions." Incorrect. Voulez-vous dire comment les types peuvent implémenter des méthodes sans être explicites à ce sujet? Le compilateur détecte l'appartenance à l'interface de type. C'est rapide. "Les fonctions intégrées sont de nature plus générale" non, les fonctions intégrées sont, comme tout le reste, compilées. La même chose se produit avec les modèles C ++. "l'absence d'une hiérarchie de types (comme Java ou C ++) donne à Go un inconvénient de vitesse" - incorrect, une hiérarchie de types n'a rien à voir avec l'exécution à l'exécution.
Malcolm