web-dev-qa-db-fra.com

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

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 cela peut-il être, sachant que le compilateur Go produit du code natif pour l'exécution?
Compilateurs immatures pour Go? Ou il y a un problème intrinsèque avec la langue Go?

MODIFIER:
La plupart des réponses nient la lenteur intrinsèque de Go languge, affirmant que le problème réside dans les compilateurs immatures.
J'ai donc fait mes propres tests pour calculer les nombres de Fibonacci : L'algorithme itératif s'exécute en Go (freebsd, 6g) avec la vitesse same comme en C (avec O3 option). Le terne récursif s'exécute dans Go 2 times plus lent qu'en C (avec l'option -O3; avec -O0 - identique). Mais je n'ai pas vu tomber 10 fois comme dans le jeu de référence.

109
Oleg Razgulyaev

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 eux-mêmes rapidement et produire du code correct (il y a un peu d'optimisation). gccgo utilise les passes d'optimisation existantes de GCC et pourrait fournir une comparaison plus pointue 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 grand-chose à voir avec la langue en tant que telle, sauf dans la mesure où l'implémentation passe à l'exécution des fonctionnalités de langage dont la référence n'a pas vraiment besoin. Dans la plupart des langues compilées, 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 d'utilisateurs réels de la langue écriraient des programmes qui n'utilisaient pas cette fonctionnalité . Déplacez les choses sans les supprimer complètement (par exemple, prédire les destinations d'appels virtuels dans Java compilé JIT) commence à devenir difficile.

FWIW, mon propre test très trivial avec Go lorsque j'y jetais un coup d'œil (une boucle d'addition d'entiers, en gros), gccgo a produit du code vers l'extrémité rapide de la plage entre gcc -O0 et gcc -O2 pour l'équivalent C. Go n'est pas intrinsèquement lent, mais les compilateurs ne font pas encore tout. Pas étonnant pour une langue de 10 minutes.

100
Steve Jessop

Dans la prochaine version de la Go FAQ , quelque chose de similaire au suivant 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 le fait assez mal, dont plusieurs dans test/bench. Les plus lents 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 dans un assembleur optimisé). Les repères qui dépendent des expressions régulières (regex-dna, par exemple) comparent essentiellement le package 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 un réglage approfondi et les versions Go de la plupart des références 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 langues sont beaucoup plus proches en termes de performances brutes que ne l'indique cette suite.

Il y a encore place à amélioration. Les compilateurs sont bons mais pourraient être meilleurs, de nombreuses bibliothèques ont besoin d'un travail de performance majeur et le garbage collector 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.

Collecte des ordures et performances dans gccgo (1)

garbage collection et performances dans gccgo (2)

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

50
peterSO

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

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

Go ne fera que s'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 non de minuscules références de calcul. Pour moi, Go a apparemment abouti à un programme plus efficace que ce que je pouvais produire en Python. C'est mon point de vue sur la réponse à cette question.

34
jdi

Les choses ont changé.

Je pense que la réponse correcte 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, il n'est toujours pas aussi rapide que C, mais il est loin d'être 10 fois plus lent, dans un sens général.

Jeu de benchmarks en 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 la référence 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%
6
tiffon

Malgré l'efficacité moins bonne de Go sur l'utilisation des cycles CPU, 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 ring-ring , Go était 16x plus rapide que Java. Dans le même scénario, Go CSP était presque comparable à C++, mais en utilisant 4 fois moins de mémoire.

La grande puissance du langage Go est son modèle de concurrence, Communicating Sequential Processes, CSP, spécifié par Tony Hoare dans les années 70, étant simple à mettre en œuvre et adapté aux besoins hautement concurrents.

5
DLopes

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 incorporer des appels de fonction virtuelle à travers plusieurs niveaux, même avec les classes OO, basées sur le profil d'exécution. Ce n'est pas possible dans un langage compilé statiquement (bien que la recompilation plus récente soit basée sur le profil enregistré) Cela peut être 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 l'ensemble de l'exécution - souvent ignorée car le programme se termine avant que toutes les ordures ne soient collectées.

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 dans son cœur - les humains ont du mal à accepter qu'avec une formation appropriée 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 la programmation en C pour commencer.

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

Enfin, les gens qualifient le "jeu de repères de langage informatique" de "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, c'est du click-bait, de fausses nouvelles, conçu pour générer du trafic sur le site.

Pour finir, dernière note ... J'ai exécuté 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 drapeau rouge pour tout ingénieur sérieux.

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

1
robert engels

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 liées tardivement (à l'exécution). Le hotspot JIT décide au RUNTIME des méthodes à intégrer, il peut même ajuster la disposition des données à la taille du cache/à l'architecture du processeur sur lequel il est actuellement exécuté. C/C++ en général peut compenser (et dans l'ensemble, il fonctionnera toujours mieux) en ayant un accès direct au matériel. Pour Go, les choses peuvent sembler différentes car elles sont de plus haut niveau par rapport à C, mais il manque actuellement un système/compilateur d'optimisation de l'exécution. Mon instinct me dit, Go pourrait être plus rapide que Java car Go n'impose pas de pointeur chassant autant et encourage une meilleure structure de données locality + nécessite moins d'allocation.

1
R.Moeller

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

1
Dan Marinescu

sous linux, le go runtime est super rapide, parfaitement comparable à c/c ++. le temps d'exécution go sous windows et unix ne sont pas dans la même ligue

comparaison avec Java n'est pas si important, allez pour le développement du système et des applications (comme Java ressemble plus à un col bleu pour le développement d'applications uniquement). ne sera pas entrez les détails, mais lorsque des choses comme kubernetes sont écrites, vous vous rendez compte que ce n'est pas un jouet convivial pour les consultants en 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 des applications, a des pointeurs, une allocation de mémoire et une désallocation efficaces, évite les complications résultant de l'héritage d'implémentation oh si facile à manquer, vous donnant des co-routines et autres modernes façons d'écrire des applications hautes performances dans les délais et le budget. encore une fois, go est super rapide sous linux, ce qui est exactement ce pour quoi il a été conçu (très heureux qu'il le fasse)

0
Dan Marinescu