Parfois, Java surpasse le C ++ dans les tests de performance. Bien sûr, parfois, C ++ surpasse.
Voir les liens suivants:
- http://keithlea.com/javabench/
- http://blog.dhananjaynene.com/2008/07/performance-comparison-c-java-python-ruby-jython-jruby-groovy/
- http://blog.cfelde.com/2010/06/c-vs-java-performance/
Mais comment est-ce possible? Cela me dépasse de penser que le bytecode interprété pourrait être plus rapide qu'un langage compilé.
Quelqu'un peut-il s'il vous plaît expliquer? Merci!
java
c++
performance
Deets McGeets
la source
la source
Réponses:
Premièrement, la plupart des machines virtuelles incluent un compilateur, le "code octet interprété" est en fait assez rare (du moins dans le code de référence - ce n'est pas aussi rare dans la réalité, où votre code est généralement plus que quelques boucles triviales qui se répètent extrêmement souvent ).
Deuxièmement, bon nombre de points de repère impliqués semblent assez biaisés (que ce soit par intention ou par incompétence, je ne peux pas vraiment dire). Par exemple, il y a des années, j'ai examiné une partie du code source lié à l'un des liens que vous avez publiés. Il y avait un code comme ceci:
Puisque
calloc
fournit une mémoire qui a déjà été mise à zéro, utiliser à nouveau lafor
boucle est évidemment inutile. Cela a été suivi (si la mémoire le permet) par le remplissage de la mémoire avec d’autres données (sans aucune dépendance quant à leur remise à zéro), de sorte que toute la remise à zéro était totalement inutile de toute façon. Remplacer le code ci-dessus par un simplemalloc
(comme toute personne saine d'esprit l'aurait utilisée au départ) améliorait suffisamment la vitesse de la version C ++ pour battre la version Java (avec une marge assez large, si la mémoire le permet).Prenons (pour un autre exemple) le
methcall
repère utilisé dans l'entrée de blog de votre dernier lien. Malgré son nom (et son apparence possible), la version C ++ de cet outil ne mesure pas grand-chose du tout sur le temps système d'appel de méthode. La partie du code qui s'avère critique est dans la classe Toggle:La partie critique s'avère être le
state = !state;
. Considérez ce qui se passe lorsque nous modifions le code pour coder l'étatint
de la manière suivantebool
:Ce changement mineur améliore la vitesse globale d'environ 5: 1 . Bien que l' objectif ait été conçu pour mesurer le temps d'appel d'une méthode, en réalité, il s'agissait essentiellement du temps nécessaire pour effectuer la conversion entre
int
etbool
. Je conviens certainement que l'inefficacité montrée par l'original est regrettable - mais étant donné que cela semble rarement apparaître dans un code réel, et qu'il est facile de le réparer quand / si cela se produit, j'ai du mal à penser de cela comme signifiant beaucoup.Au cas où quelqu'un déciderait de réexécuter les tests de performance impliqués, je devrais également ajouter qu'il y a une modification presque aussi triviale à la version Java qui produit (ou au moins une fois produite - je n'ai pas réexécuté les tests avec une JVM récente pour confirmer encore) une amélioration assez substantielle de la version Java également. La version Java a un NthToggle :: activate () qui ressemble à ceci:
Changer cela pour appeler la fonction de base au lieu de manipuler
this.state
directement donne une amélioration assez rapide de la vitesse (mais pas assez pour suivre la version modifiée de C ++).Nous nous retrouvons donc avec une fausse hypothèse sur les codes d’octets interprétés par rapport à certains des pires points de repère (que j’ai jamais vus). Ni donne un résultat significatif.
Selon ma propre expérience, avec des programmeurs tout aussi expérimentés qui accordent autant d’attention à l’optimisation, C ++ battra Java le plus souvent - mais (au moins entre ces deux), le langage fera rarement autant de différence que les programmeurs et le concepteur. Les repères cités nous en disent plus sur l’inaptitude / la (mauvaise) honnêteté de leurs auteurs que sur les langues qu’ils prétendent comparer.
[Edit: Comme suggéré dans un endroit ci-dessus mais jamais indiqué aussi directement que je devrais probablement avoir, les résultats que je cite sont ceux que j’ai obtenus lorsque j’ai testé cela il y a environ 5 ans, en utilisant des implémentations C ++ et Java qui étaient courantes à cette époque. . Je n'ai pas relancé les tests avec les implémentations actuelles. Un coup d'œil, cependant, indique que le code n'a pas été corrigé, donc tout ce qui aurait changé serait la capacité du compilateur à dissimuler les problèmes dans le code.]
Cependant, si nous ignorons les exemples Java, il est en fait possible que le code interprété s'exécute plus rapidement que le code compilé (bien que difficile et quelque peu inhabituel).
Cela se produit généralement de la manière suivante: le code en cours d'interprétation est beaucoup plus compact que le code de la machine ou s'exécute sur un processeur doté d'un cache de données plus important que le cache de code.
Dans un tel cas, un petit interprète (par exemple, l'interprète interne d'une implémentation Forth) peut être entièrement inséré dans le cache de code et le programme qu'il interprète s'inscrit entièrement dans le cache de données. Le cache est généralement plus rapide que la mémoire principale d'au moins 10 fois, et souvent beaucoup plus (un facteur de 100 n'est plus particulièrement rare).
Donc, si le cache est plus rapide que la mémoire principale d'un facteur N et qu'il faut moins de N instructions de code machine pour implémenter chaque code d'octet, le code d'octet devrait gagner (je simplifie, mais je pense que l'idée générale devrait tout de même être apparent).
la source
Le C / C ++ réalisé à la main par un expert au temps illimité sera au moins aussi rapide ou plus rapide que Java. En fin de compte, Java lui-même est écrit en C / C ++, ce qui vous permet bien sûr de faire tout ce que Java fait si vous êtes prêt à fournir suffisamment d’ingénierie.
Cependant, dans la pratique, Java s’exécute souvent très vite pour les raisons suivantes:
Dans le même temps, le C / C ++ présente également certains avantages:
Global:
la source
Le runtime Java n'interprète pas le bytecode. Au lieu de cela, il utilise ce qui s'appelle Compilation Just In Time . Fondamentalement, lorsque le programme est exécuté, il prend du bytecode et le convertit en code natif optimisé pour le processeur en question.
la source
Toutes choses étant égales par ailleurs, vous pourriez dire: non, Java ne devrait jamais être plus rapide . Vous pouvez toujours implémenter Java en C ++ à partir de zéro et ainsi obtenir des performances au moins aussi bonnes. En pratique cependant:
En passant, cela me rappelle le débat sur le carbone dans les années 80/90. Tout le monde se demandait "C peut-il être aussi rapide que l’assemblée?". En gros, la réponse était: non sur papier, mais en réalité, le compilateur C avait créé un code plus efficace que 90% des programmeurs d’assemblage (enfin, une fois qu’il a mûri un peu).
la source
http://www.ibm.com/developerworks/java/library/j-jtp09275/index.html
la source
Bien qu'un programme Java entièrement optimisé l'emporte rarement sur un programme C ++ complètement optimisé, des différences comme la gestion de la mémoire peuvent rendre beaucoup d'algorithmes implémentés idiomatiquement en Java plus rapidement que les mêmes algorithmes implémentés en C ++.
Comme @Jerry Coffin l'a souligné, il existe de nombreux cas dans lesquels de simples modifications peuvent rendre le code beaucoup plus rapide, mais il faut souvent trop de peaufiner les modifications impures dans une langue ou dans une autre pour que l'amélioration des performances en vaille la peine. C'est probablement ce que vous verriez dans un bon benchmark montrant que Java se comporte mieux que le C ++.
De plus, bien que généralement pas si significatif que cela, il existe certaines optimisations de performances qu'un langage JIT comme Java peut faire que C ++ ne peut pas. Le runtime Java peut inclure des améliorations après la compilation du code, ce qui signifie que le JIT peut potentiellement produire un code optimisé pour tirer parti des nouvelles fonctionnalités (ou du moins différentes) de la CPU. Pour cette raison, un binaire Java de 10 ans peut potentiellement surperformer un binaire C ++ de 10 ans.
Enfin, la sécurité de type complète dans son ensemble peut, dans de très rares cas, offrir des améliorations de performances extrêmes. Singularity , un système d'exploitation expérimental écrit presque entièrement dans un langage basé sur C #, offre une communication interprocessus et des tâches multitâches beaucoup plus rapides, du fait qu'il n'est pas nécessaire de définir des limites de processus matériels ni de changer de contexte coûteux.
la source
Publié par Tim Holloway sur JavaRanch:
Source: http://www.coderanch.com/t/547458/Performance/java/Ahead-Time-vs-Just- time
la source
En effet, la dernière étape de la génération du code machine se déroule de manière transparente dans la JVM lors de l’exécution de votre programme Java, au lieu d’être explicite lors de la construction de votre programme C ++.
Vous devez tenir compte du fait que les machines JVM modernes passent beaucoup de temps à compiler le code d'octet à la volée en code machine natif pour le rendre aussi rapide que possible. Cela permet à la machine virtuelle Java de faire toutes sortes d’astuces de compilation qui peuvent être encore meilleures en connaissant les données de profilage du programme en cours d’exécution.
Une chose telle que l’insertion automatique d’un getter, de sorte qu’un retour rapide ne soit pas nécessaire pour obtenir une valeur, accélère les choses.
Cependant, ce qui a vraiment permis des programmes rapides, c'est de mieux nettoyer après. Le mécanisme de récupération de place en Java est plus rapide que le manuel sans malloc en C. De nombreuses implémentations modernes sans malloc utilisent un collecteur de mémoire en dessous.
la source
Réponse courte - ce n'est pas. Oubliez ça, le sujet est aussi vieux que le feu ou la roue. Java ou .NET n'est pas et ne sera pas plus rapide que C / C ++. C'est assez rapide pour la plupart des tâches pour lesquelles vous n'avez pas du tout besoin de penser à l'optimisation. Comme les formulaires et le traitement SQL, mais c'est là que tout se termine.
Pour les tests de performance ou les petites applications écrites par des développeurs incompétents, le résultat final sera que Java / .NET sera probablement proche et peut-être même plus rapide.
En réalité, des choses simples comme l'allocation de mémoire sur une pile ou simplement l'utilisation de memzones vont tout simplement tuer le Java / .NET sur le champ.
Le monde ramassé des ordures utilise une sorte de memzone avec toute la comptabilité. Ajoutez de la memzone à C et C sera plus rapide sur place. Surtout pour les benchmarks "code haute performance" Java vs C, qui vont comme ceci:
Essayez d'utiliser des variables basées sur la pile en C / C ++ (ou un nouveau placement), elles se traduisent en
sub esp, 0xff
une instruction x86 unique. Battez-le avec Java - vous ne pouvez pas ...La plupart du temps, je vois ces bancs où la comparaison de Java avec C ++ est comparée. Stratégies d’allocation de mémoire incorrectes, conteneurs à croissance automatique sans réserves, plusieurs nouveaux. Cela n’est même pas proche du code C / C ++ orienté performances.
Aussi une bonne lecture: https://days2011.scala-lang.org/sites/days2011/files/ws3-1-Hundt.pdf
la source
En réalité, ce ne sont que des assembleurs de haut niveau qui font exactement ce que le programmeur leur dit, exactement comme le programmeur le leur dit dans l'ordre exact indiqué par le programmeur. Les différences de performances sont si minimes qu'elles sont sans importance pour tous les objectifs pratiques.
La langue n'est pas "lente", le programmeur a écrit un programme lent. Il est très rare qu'un programme écrit de la meilleure façon dans une langue dépasse (à quelque fin pratique que ce soit) un programme faisant la même chose en utilisant le meilleur moyen d'une autre langue, à moins que l'auteur de l'étude ne veuille écraser son axe.
Évidemment, si vous allez dans un cas rare comme les systèmes embarqués en temps réel, le choix de la langue peut faire la différence, mais à quelle fréquence est-ce le cas? et de ces cas, combien de fois le bon choix n'est-il pas aveuglément évident?
la source
Keith Lea vous dit qu'il y a des "imperfections évidentes" mais ne fait rien à propos de ces "imperfections évidentes". En 2005, ces anciennes tâches avaient été abandonnées et remplacées par les tâches figurant maintenant dans le jeu de test de performance .
Keith Lea vous dit qu'il "a pris le code de référence pour C ++ et Java de Great Computer Language Shootout, désormais obsolète, et qu'il a effectué les tests", mais il n'affiche les mesures que pour 14 des 25 tests obsolètes .
Keith Lea vous dit maintenant qu'il n'essayait pas de prouver quoi que ce soit avec le blog, sept ans auparavant, mais à l'époque, il avait déclaré: "J'en ai marre d'entendre les gens dire que Java était lent, quand je sais que c'est assez rapide ...", ce qui suggère à l'époque, il essayait de prouver quelque chose.
Christian Felde vous dit "Je n'ai pas créé le code, j'ai simplement relancé les tests." en tant que -si cela le dégage de toute responsabilité dans sa décision de publier les mesures des tâches et des programmes sélectionnés par Keith Lea.
Les mesures de 25 programmes, même minuscules, fournissent-elles des preuves définitives?
Ces mesures concernent les programmes exécutés en "mode mixte". Java n'est pas interprété par Java - "N'oubliez pas le fonctionnement de HotSpot." Vous pouvez facilement savoir dans quelle mesure Java exécute le "code octet interprété", car vous pouvez forcer Java à n'interpréter que le code temporel - il suffit simplement que certains programmes Java s'exécutent avec et sans l'option -Xint.
la source
Cela m'amuse à quel point cette notion étrange de "code codé interprété" est omniprésente. Avez-vous déjà entendu parler de la compilation JIT? Votre argument ne peut pas être appliqué à Java.
Mais, mis à part JVM, il peut arriver qu'un code à thread direct ou même une interprétation triviale de bytecode puisse facilement surpasser un code natif fortement optimisé. L'explication est assez simple: le bytecode peut être assez compact et conviendra à votre cache minuscule lorsqu'une version de code natif du même algorithme aura plusieurs échecs de cache pour une seule itération.
la source
JIT, GC et ainsi de suite, C ++ peut être très, très facilement rendu beaucoup plus lent que Java. Cela n'apparaîtra pas dans les tests, mais la même application écrite par un développeur Java et un développeur C ++ peut être beaucoup plus rapide en Java.
En ce qui concerne les modèles d'héritage avancés, ils sont à peu près similaires - C ++ en a que Java ne possède pas et vice-versa, mais tous introduisent également une surcharge significative et similaire. Donc, pas d'avantage spécial C ++ dans la programmation lourde d'objet.
Encore une mise en garde: le CPG peut être plus rapide ou plus lent que la gestion manuelle des allocations. Si vous affectez un grand nombre de petits objets, dans l’environnement du GC, une partie de la mémoire est généralement allouée et une partie de celle-ci est envoyée selon les besoins pour les nouveaux objets. En mode géré - chaque objet = une allocation distincte prend un temps considérable. OTOH, si vous malloc () beaucoup de mémoire à la fois et que vous assignez ensuite simplement des morceaux de celle-ci à vos objets manuellement, ou utilisez quelques instances d'objets plus grandes, vous pouvez arriver beaucoup plus rapidement.
la source
obj.fetchFromDatabase("key")
trois fois sur cinq lignes de code pour la même clé, vous réfléchirez à deux fois s'il faut extraire cette valeur une fois et la mettre en cache dans une variable locale. Si vous écrivezobj->"key"
avec->
une surcharge surchargée pour agir comme une extraction de base de données, vous êtes beaucoup plus enclin à le laisser passer car le coût de l'opération n'est pas évident.D'une manière ou d'une autre Stack Exchange ne prend pas mes autres points de pile, donc ... pas de réponse malheureusement ...
Cependant, la deuxième réponse la plus votée est pleine de désinformation à mon humble avis.
Une application personnalisée par un expert en C / C ++ est TOUJOURS beaucoup plus rapide qu'une application Java, tout simplement. Il n'y a pas "aussi vite que Java ou plus rapide". c'est simplement plus rapide, précisément à cause des éléments que vous citez ci-dessous:
Compilation JIT : Vous attendez-vous vraiment à ce que l'optimiseur automatique ait les connaissances d'un programmeur expert et voie le lien entre l'intention et le code que le processeur va réellement exécuter? De plus, tout le JIT que vous faites est du temps perdu par rapport à un programme déjà compilé.
Garbage Collection est un outil qui désalloue simplement des ressources qu'un programmeur aurait oublié de désallouer, de manière plus ou moins efficace.
Évidemment, cela ne peut être que plus lent que ce qu'un expert (vous avez choisi le terme) que le programmeur C ferait pour gérer sa mémoire (et non, il n'y a pas de fuites dans les applications correctement écrites).
Une application C optimisée en performances connaît le processeur sur lequel elle est exécutée, elle a été compilée dessus, sinon, vous n’avez pas tout à fait pris en compte toutes les étapes en termes de performances, n’est-ce pas?
Statistiques d'exécution Cela dépasse mes connaissances, mais je soupçonne qu'un expert en C dispose de suffisamment de connaissances en prédiction de branche pour déjouer l'optimisation automatisée -
De très bonnes bibliothèques De nombreuses fonctions peu optimisées sont facilement disponibles dans les bibliothèques en Java. Il en va de même dans tous les langages. Cependant, les bibliothèques les plus optimisées sont écrites en C, en particulier pour le calcul.
La JVM est une couche d'abstraction, qui implique à la fois de bonnes choses, dont beaucoup sont au-dessus, et implique également que la solution globale est plus lente par conception.
Global:
Java ne peut jamais atteindre la vitesse de C / C ++ en raison de la manière dont il fonctionne dans une machine virtuelle avec beaucoup de protection, de fonctionnalités et d’outils.
Le logiciel optimisé, que ce soit pour l'informatique ou les jeux, est clairement défini par C ++, et il est courant de voir les implémentations C ++ remporter des concours de codage à un point tel que les meilleures implémentations Java ne peuvent être vues que sur la deuxième page.
En pratique, C ++ n'est pas un jouet et ne vous laissera pas faire avec beaucoup d'erreurs que la plupart des langages modernes peuvent gérer. Cependant, en étant plus simple et moins sûr, il est intrinsèquement plus rapide.
Et pour conclure, je voudrais dire que la plupart des gens ne donnent pas deux centimes à ce sujet, qu’en fin de compte, l’optimisation est un sport réservé à très peu de développeurs chanceux et que, sauf dans les cas où la performance est vraiment une préoccupation (Par exemple, si multiplier le matériel par 10 ne vous aidera pas - ou ne représentera que quelques millions au minimum), la plupart des gestionnaires préféreront une application non optimisée et une tonne de matériel.
la source
new
oumalloc()
. Cela peut être beaucoup plus rapide en général que n'importe quelle gestion de mémoire manuelle, car vous ne seriez pas en mesure de déplacer des objets manuellement. Donc, tout votre raisonnement est clairement faux et partial. Votre connaissance des algorithmes GC et des méthodes d'optimisation JIT est trop limitée.J'ai vu au moins deux impressionnants mmo réalisés en Java. Dire que ce n'est pas assez rapide pour les jeux est un abus de langage. Si les concepteurs de jeux préfèrent le C ++ à d’autres langages, cela signifie simplement que ces programmeurs n’ont jamais vraiment abordé d’autres paradigmes / langages de programmation. N'importe quel langage aussi avancé que C / C ++ ou même Java peut produire du code qui pourrait techniquement répondre ou vaincre l'argument speed. Tout cela est dit et bien dit, ce que les programmeurs savent, avec quelles équipes travaillent le plus et surtout pourquoi ils utilisent ces outils. Puisque nous abordons l’aspect développement de jeux de la programmation, il doit y avoir plus d’arguments. Tout simplement le ' C’est une question d’argent et de temps pour une entreprise qui utilise des outils qui répondent aux critères d’AQ et dans le monde réel n’a aucune influence sur xx raisons qui poussent à choisir C ++ au lieu de Java ou de tout autre langage. C'est juste une décision de production en masse. Au niveau le plus élémentaire des algorithmes informatiques, nous ne jouons qu'avec des zéros et des uns, l'argument vitesse est l'un des arguments les plus stupides jamais appliqués au jeu. Si vous voulez des gains de vitesse aussi importants, supprimez complètement les langages de programmation et travaillez avec un assemblage qui constitue de loin le meilleur avantage.
la source