web-dev-qa-db-fra.com

Java Performances d'exécution VS Native C / C ++ Code?

Je suis devenue une programmation de plus en plus confortable dans Java qu'avec C++ ou C. J'espère avoir une idée du succès de la performance engagée à l'aide d'un interprète JVM, par opposition à l'exécution de la même chose " Projet "Nativement. Je me rends compte qu'il existe un certain niveau de subjectivité ici; la qualité du programme dépendra fortement d'une bonne mise en œuvre. Je suis intéressé par les aspects suivants dans un sens général:

  • Il doit y avoir une base de référence pour les frais généraux lors de l'utilisation d'un interprète. Existe-t-il une règle générale à retenir? 10% 15%? (J'ai tiré ces chiffres d'air mince) J'ai lu le blog occasionnel indiquant que Java code est presque aussi rapide que le code natif, mais je pense que cela peut avoir été biaisé.

  • Le collecteur de poubelles JVM a-t-il ajouté des frais généraux significatifs aux performances d'exécution? Je sais que les applications de cacao ont commencé à utiliser un modèle de collecte des ordures et je conviens que cela rend la programmation beaucoup plus simple, mais à quel coût?

  • Quelle est la surcharge de faire des appels système de Java? Par exemple, la création d'un objet de prise par opposition à l'API de socket C.

  • Enfin, je me souviens de lire quelque part que la mise en œuvre JVM est unique. Si cela est vrai (ce que je suis sceptique), cela signifie-t-il que Java threads ne sont vraiment pas vrais threads? Est-ce que a Java thread, en général , correspond à un thread sous-jacent fourni au noyau? Est-ce que A Java offre-t-il de la même manière qu'une application native de plusieurs cœurs/multiples CPU?

Tout conseiller du développeur qui comprend les subtilités de JVM et Java Performance du programme serait très appréciée. Merci.

40
D.C.

Java n'est pas une langue interprétée et n'a pas été pour plusieurs versions. Le Java bytecode est Jit'ed à la volée. (Techniquement, il interprète toujours une partie du code, mais tout ce qui compte performance-sage obtient Jit'ed)

En ce qui concerne la performance, qu'est-ce que sur Terre vous donne l'idée folle que "il y a une base pour les frais généraux"? Il n'y a pas. Il n'y avait jamais eu et ne sera jamais. Pas entre c ++ et java, et non entre Python et javascript, ou n'importe quel autre deux langues. Il y a des choses que votre version spécifique du JVM fera plus vite que votre Compilateur spécifique C++, et des choses que votre compilateur C++ spécifique fera mieux que votre JVM spécifique.

Donc, la "surcharge" de votre choix de langue dépend entièrement de 1) ce que vous voulez que votre code fasse, et 2) comment vous écrivez votre code.

Si vous prenez un Java programme et traduisez-le en C++, le résultat fonctionnera presque certainement plus lentement.

Si vous prenez un programme C++ et traduisez-le en Java, cela fonctionnera également plus lentement.

Pas parce qu'une langue est "plus rapide" que l'autre, mais parce que le programme d'origine a été écrit pour une langue et a été adapté à bien travailler dans que langue. Et toute tentative de traduire en une autre langue perdra cet avantage. Vous vous retrouvez avec un style C++ - style Java Program, qui ne sera pas exécuté efficacement sur le programme JVM ou un programme Java-style C++, qui fonctionnera terriblement comme bien.

Aucune spécification linguistique ne contient une clause selon laquelle "et le résultat doit être au moins x% plus lent que la langue y". Votre compilateur C++ et JVM font de leur mieux pour que les choses puissent aller vite.

Et puis les caractéristiques de performance que vous voyez aujourd'hui peuvent changer demain. Les langues n'ont pas de vitesse.

Mais pour répondre à vos questions spécifiques:

Il doit y avoir une base de référence pour les frais généraux lors de l'utilisation d'un interprète. Existe-t-il une règle générale à retenir? 10% 15%? J'ai lu le blog occasionnel indiquant que Java code est presque aussi rapide que le code natif, mais j'aurais pu être biaisé.

Comme dit ci-dessus, cela dépend. Pour de nombreuses tâches courantes, vous ne verrez généralement plus que quelques-unes différence des percents de chaque sens. Pour certains cas d'utilisation, vous verrez une différence plus grande (aller de toute façon. Les deux langues ont des avantages en matière de performance. Il y a des frais généraux associés à la JVM, mais il existe également d'énormes opportunités d'optimisation et notamment le collecteur des ordures).

Le collecteur de poubelles JVM a-t-il ajouté des frais généraux significatifs aux performances d'exécution? Je sais que les applications de cacao ont commencé à utiliser un modèle de collecte des ordures et je conviens que cela rend la programmation beaucoup plus simple, mais à quel coût?

Fondamentalement aucun. En moyenne, un collecteur d'ordures est loin plus rapide que la gestion de la mémoire manuelle, pour de nombreuses raisons:

  • sur un tas de géré, des allocations dynamiques peuvent être faites beaucoup plus vite
  • la propriété partagée peut être traitée avec des coûts amortis négligeables, où dans une langue maternelle, vous devez utiliser un comptage de référence qui est terriblement coûteux.
  • dans certains cas, la destruction de l'objet est également considérablement simplifiée (la plupart Java objets peut être récupérée juste en gisant le bloc de mémoire. En C++ Destructeurs doivent toujours être exécuté et presque chaque objet en a un)

Le principal problème avec un GC est que, bien que, en moyenne, un collecteur de déchets fonctionne mieux, vous perdez un certain contrôle sur lorsque pour prendre le coût de la performance. La gestion de la mémoire manuelle garantit que votre thread ne sera jamais arrêtée en attendant que la mémoire soit nettoyée. Un collecteur à ordures peut, à tout moment, décider de mettre en pause le processus et de nettoyer la mémoire. Dans presque tous les cas, cela est suffisamment rapide pour ne pas être un problème, mais pour des substances vitales en temps réel, c'est un problème.

(Un problème supplémentaire est que vous perdez un peu d'expressivité. En C++, Raii est utilisé pour gérer toutes sortes de ressources. En Java, vous ne pouvez pas utiliser Raii. Au lieu de cela, le GC gère la mémoire pour vous et pour toutes les autres ressources, Vous êtes vissé et je dois le faire vous-même avec beaucoup d'essai/enfin blocs. Il n'y a aucune raison pour que Raii ne puisse pas être mis en œuvre dans une langue GC'ed, mais ce n'est pas disponible dans l'une ou l'autre Java ou C #)

Quelle est la surcharge de faire des appels système de Java? Par exemple, la création d'un objet de prise par opposition à l'API de socket C.

À peu près la même chose. Pourquoi serait-il différent? Bien sûr, Java doit invoquer les services d'exploitation et API pertinents, il existe donc un peu de frais généraux, mais ce n'est vraiment rien à remarquer.

Enfin, je me souviens de lire quelque part que la mise en œuvre JVM est unique. Si cela est vrai (ce que je suis sceptique), cela signifie-t-il que Java threads ne sont vraiment pas vrais threads? Est-ce que a Java thread, en général , correspond à un thread sous-jacent fourni au noyau? Est-ce que A Java offre-t-il de la même manière qu'une application native de plusieurs cœurs/multiples CPU?

Java peut utiliser plusieurs threads, oui. Le JVM lui-même peut être singuléthralé (en ce sens que tous les services JVM fonctionnent sur le même fil), je ne sais pas à ce sujet. Mais votre Java Application peut utiliser autant de threads que tel qu'il l'aime, et ils sont mappés sur des threads OS et utiliseront plusieurs cœurs.

53
jalf

Reportez-vous ICI , pour une comparaison détaillée.

17
Adeel Ansari

Les deux Java et c # (et objectif-c) ne sont pas aussi rapides que le code natif peut être. Mais cela ne compte que si vous avez un problème où vous n'êtes pas d'ingénierie limitée. Parce que vous Je vais avoir le temps de concevoir un meilleur algorithme avec une langue de haut niveau.

Donc, fondamentalement, si vous développez un appareil dans lequel vous allez construire un million par an ou que la batterie est alimentée, vous n'utilisez pas Java ou C # pour construire son noyau fonctionnalité. Vous pouvez ajouter un interprète LISP pour faciliter la personnalisation, cependant. Microsoft ne va pas utiliser C # pour dire le noyau de SQL Server, où la performance importe vraiment. Visual Studio d'autre part, où la SP peut s'attendre à ce que les utilisateurs puissent avoir élevé -end Matériel, peut être utilisé comme vitrine pour une technologie de productivité lente mais élevée.

Veuillez noter que je fais actuellement la majeure partie de mes programmations à Pharo Smalltalk, qui est beaucoup plus lente que Java, C # ou Objective-C, et n'est même pas l'un des plus rapides SmallTalks. La productivité atout la performance.

5
Stephan Eggermont

Pour adresser chacun de vos points:

  • Les frais généraux de interprétation code sont beaucoup plus élevés que 10-15% (je suppose que 3x-5x ou plus). Afin de descendre à 10-15%, vous devez utiliser une étape de compilation de code machine (c'est-à-dire JIT). (Essayez d'exécuter une JVM avec JIT éteint et vous verrez la perte de performance comme un rocher.)
  • La collecte des ordures a un impact sur la performance, mais je dirais que tout le monde convient que cela en vaut la peine. Si vous pouvez vous permettre les frais de compilation/d'interprétation du code d'octet, vous pouvez également vous offrir les frais généraux de GC.
  • La programmation de la prise est beaucoup plus facile dans Java qu'en C/C++, si c'est ce que vous demandez. Et performant dans le monde, la tenue d'E/S socket domine sur la surcharge Java.
  • La plupart des JVM modernes ont des fils vrais, c'est-à-dire que chaque thread Java est exécuté par un fil de noyau, permettant ainsi des threads Java d'utiliser des processeurs multi-noyau modernes.
2
JesperE

Beaucoup de gens sous-estiment la performance de Java. J'étais autrefois curieux de cela aussi et a écrit un programme simple dans Java, puis un équivalent en C (pas beaucoup plus que de faire une certaine opération avec une boucle et une matrice massive). Je ne me souviens pas de chiffres exacts, mais je sais que Java _ battre c quand le programme C n'a pas été compilé avec aucun drapeau d'optimisation (sous GCC). Comme prévu, c tiré de l'avance lorsque je l'ai enfin compilé avec une optimisation agressive. Pour être honnête, ce n'était pas une expérience scientifique de quelque manière que ce soit, mais cela m'a donné une base de connaissance de savoir où Java se tenait.

Bien sûr, Java tombe probablement plus loin lorsque vous commencez à faire des choses qui nécessitent des appels système. Cependant, j'ai vu des performances de lecture de 100 Mo/s avec des disques et du réseau avec des programmes Java fonctionnant sur le matériel modeste. Je ne sais pas ce que cela dit exactement, mais cela m'indique que c'est assez bon pour presque tout ce dont j'avais besoin.

Quant aux threads, si votre programme Java crée 2 threads, vous avez 2 réel threads.

2
exabytes18
1
Bozho

En fait, un VM peut effectuer de nombreuses optimisations à l'exécution, en fonction des informations disponibles uniquement au moment de l'exécution, qu'un compilateur C/C++ ne peut pas faire. Donc, dans la plupart des cas, le JVM sera au moins aussi vite qu'un programme indigène.

Brian Goetz répond le plus, sinon toutes vos questions dans sa conversation vers un VM universel .

1
jqno

Chose importante à noter est

Java octet code JIT compilé à beaucoup plus optimisé du code spécifique au matériel particulier

vs

Code C compilé et optimisé pour le matériel général SOil ne peut pas tirer parti des fonctionnalités fournies par du matériel spécifique

0
Xinus

Il n'y a pas de réponse facile à cela. L'écriture C Style C++ est possible (même une bonne idée), mais une fois que vous essayez de faire héritage en C, les choses deviennent laid. Donc ignorer c et aller avec Java -Vs- C++ car ils sont plus proches les uns des autres.

Pour avoir un sens réel de celui-ci, vous devez écrire deux applications relativement importantes de la même manière dans les deux langues. Si vous faites cela, utilisez-vous les classes de collection STL et Java ou écrivez-vous votre propre et portez-les entre des langues? Si vous utilisez l'original, cela dépend de la mise en œuvre plus rapide d'où vous utilisez la vôtre, vous ne testez pas la vitesse réelle de l'application.

Je dirais que vous auriez besoin d'écrire la demande aussi semblable que possible, mais utilisez les bibliothèques/idiomes spécifiques de la langue où cela a du sens. C++ et Java Code, tout en étant similaire, ont des façons différentes de faire des choses - quelque chose qui est facile dans Java peut être terriblement dur en C++ et inversement.

Une implémentation moderne de GC n'ajoute pas que beaucoup de surcharge et vous pouvez passer à A GC en C++ pour faire la comparaison si vous aimez :-)

Il y a des choses que le temps d'exécution Java peut faire cela ne se fait généralement pas dans les compilateurs C++, tels que la capacité de méthodes virtuelles en ligne.

Pour le type de système, les choses Java sont généralement des stations à faire des appels en C ainsi qu'il y a des frais générales là-bas (bien que JNI soit plus rapide qu'on ne soit utilisé).

Le threading dépend de la mise en œuvre. Soleil utilisé pour utiliser "les filets verts; pour Solaris, mais cela est parti depuis longtemps. Autant que je sache la plupart (tous?) VMS modernes utilise des threads natifs.

En bref, je ne pense pas qu'il y ait une bonne métrique sur le% de surcharge pour Java -Vs- C++, et tout ce que vous trouvez est susceptible d'être des micro-repères qui ne représentent pas le monde réel (malheureusement).

0
TofuBeer

Comme votre objectif est très modeste "J'espère avoir un sens du succès de la performance ..." Vous devriez être capable de remplir la majeure partie de celle-ci en examinant les programmes et les mesures présentées dans The Computer Language Benchmarks Game .

Comme vous le savez tous les deux Java et C++

Mais vous avez à pense À propos de si des mesures de minuscules programmes peuvent indiquer plausiblement la performance probable de votre Application .

0
igouy