Java est-il vraiment lent?

180

Java a une certaine réputation d'être lent .

  • Java est-il vraiment lent?
  • Si oui, pourquoi? Où est (ou était) le goulot d'étranglement? Est-ce à cause de JVM inefficaces? Collecte des ordures? Bibliothèques de bytecode pures au lieu de code C enveloppé JNI? De nombreux autres langages ont ces caractéristiques, mais ils n'ont pas cette réputation de lenteur.
Stefano Borini
la source
35
les gens deviennent tellement nerveux ... ne voient pas en quoi cela peut être subjectif, ni argumenter. Je me demande si une question comme "pourquoi le tri des bulles est lent" obtiendrait le même résultat. J'ai posé une question technique et je voulais des réponses techniques (que j'ai obtenues), mais clore la question comme subjective et argumentative est ridicule.
Stefano Borini
1
J'ai lu la plupart des principaux commentaires et aucun d'entre eux ne semble aborder le fait flagrant que les applications de bureau basées sur l'interface graphique C # fonctionnent beaucoup plus rapidement que toutes les applications de bureau basées sur l'interface graphique Java, y compris les applications modernes.
BobTurbo
3
En tant que développeur Web côté client qui a traité des formulaires Web .net, .net MVC, PHP, Rails, Django et une grande variété de tout sauf Spring (ce que j'ai entendu dire est bon) en Java, je m'attends à de mauvaises performances / architecture à partir de back-ends construits par des équipes Java. Je soupçonne que le vrai problème n'est pas les benchmarks, mais plutôt le fait qu'il y ait simplement une tonne de développeurs Java médiocres. Ce n'est pas la faute de la langue. Ce n'est pas la faute des développeurs Java qui perfectionnent leur métier et apprennent des langages autres que Java. Cela peut cependant être la faute de Sun, des certificats, des années 90 et de l'industrie informatique en général.
Erik Reppen

Réponses:

236

Le Java moderne est l'un des langages les plus rapides, même s'il est encore un bourreau de mémoire. Java avait la réputation d'être lent, car le démarrage de la machine virtuelle prenait beaucoup de temps.

Si vous pensez toujours que Java est lent , consultez les résultats du jeu de référence . Un code étroitement optimisé écrit dans un langage compilé à l'avance (C, Fortran, etc.) peut le battre; cependant, Java peut être plus de 10 fois plus rapide que PHP, Ruby, Python, etc. Il existe des domaines spécifiques où il peut battre les langages compilés courants (s'ils utilisent des bibliothèques standard).

Il n'y a aucune excuse pour les applications Java "lentes" maintenant.Les développeurs et les anciens codes / bibliothèques sont à blâmer, bien plus que le langage. Aussi, blâmez n'importe quoi «entreprise».

Pour être juste envers la foule «Java est lent», voici les domaines où il est encore lent (mis à jour pour 2013):

  • Les bibliothèques sont souvent écrites pour «l'exactitude» et la lisibilité, pas pour les performances. À mon avis, c'est la principale raison pour laquelle Java a toujours une mauvaise réputation, en particulier côté serveur. Cela aggrave les problèmes de String de manière exponentielle. Certaines erreurs simples sont courantes: les objets sont souvent utilisés à la place des primitives, ce qui réduit les performances et augmente l'utilisation de la mémoire. De nombreuses bibliothèques Java (y compris les bibliothèques standard) créeront des chaînes fréquemment, plutôt que de réutiliser des formats mutables ou plus simples (char [] ou StringBuffer). C'est lent et crée des tonnes de déchets à ramasser plus tard. Pour résoudre ce problème, je suggère aux développeurs d'utiliser des collections primitives et en particulier les bibliothèques de Javalution, lorsque cela est possible.

  • Les opérations sur les chaînes sont un peu lentes. Java utilise des objets chaîne immuables codés en UTF-16 . Cela signifie que vous avez besoin de plus de mémoire, plus d'accès à la mémoire et certaines opérations sont plus complexes qu'avec ASCII (C, C ++). À l'époque, c'était la bonne décision pour la portabilité, mais cela entraîne un faible coût de performance. UTF-8 semble être un meilleur choix maintenant.

  • L'accès au tableau est un peu plus lent que C, en raison des vérifications des limites. La pénalité était autrefois importante, mais elle est maintenant petite (Java 7 optimise de nombreuses vérifications de limites redondantes).

  • Le manque d'accès arbitraire à la mémoire peut ralentir certaines E / S et certains traitements au niveau du bit (compression / décompression par exemple). C'est une caractéristique de sécurité de la plupart des langages de haut niveau actuellement.

  • Java utilise BEAUCOUP plus de mémoire que C, et si votre application est liée à la mémoire ou à la bande passante mémoire (mise en cache, etc.), cela la ralentit. Le revers de la médaille est que l'allocation / désallocation est extrêmement rapide (hautement optimisée). C'est une caractéristique de la plupart des langages de haut niveau maintenant, et en raison des objets et de l'utilisation de GC plutôt que de l'allocation de mémoire explicite. Plus de mauvaises décisions de la bibliothèque.

  • Les E / S basées sur les flux sont lentes car (OMI, mauvais choix) nécessitent une synchronisation à chaque accès au flux. NIO a corrigé ce problème , mais c'est pénible à utiliser. On peut contourner ce problème en faisant de la lecture / écriture dans un tableau, au lieu d'un élément à la fois.

  • Java ne fournit pas les mêmes fonctionnalités de bas niveau que C, vous ne pouvez donc pas utiliser des astuces d'assembleur en ligne sales pour accélérer certaines opérations. Cela fournit la portabilité et est une caractéristique de la plupart des langages de haut niveau maintenant.

  • Il est courant de voir des applications Java liées à de très anciennes versions de JVM. Surtout côté serveur. Ces anciennes machines virtuelles Java peuvent être incroyablement inefficaces par rapport aux dernières versions.

En fin de compte, Java a été conçu pour assurer la sécurité et la portabilité au détriment de certaines performances, et pour certaines opérations très exigeantes, cela montre. La plupart de sa réputation de lenteur n'est plus méritée.


Cependant, il existe plusieurs endroits où Java est plus rapide que la plupart des autres langages:

  • L'allocation et la désallocation de mémoire sont rapides et bon marché.J'ai vu des cas où il est 20% PLUS RAPIDE (ou plus!) D'allouer un nouveau tableau de plusieurs Ko que de réutiliser un tableau mis en cache.

  • L'instanciation d'objets et les fonctionnalités orientées objet sont extrêmement rapides à utiliser (plus rapides que C ++ dans certains cas), car elles sont conçues depuis le début. Cela provient en partie d'un bon GC plutôt que d'une allocation explicite (ce qui est plus convivial pour de nombreuses allocations de petits objets). On peut coder C qui bat cela (en roulant la gestion de la mémoire personnalisée et en faisant malloc efficacement), mais ce n'est pas facile.

  • Les appels de méthode sont fondamentalement gratuits et dans certains cas plus rapides que le code de grande méthode. Le HotSpot compilateur utilise les informations d'exécution pour optimiser les appels de méthode et dispose d'une inlining très efficace. En utilisant les informations d'exécution supplémentaires, il peut parfois surpasser les compilateurs à l'avance et même (dans de rares cas) l'insertion manuelle. Comparez avec C / C ++ où les appels de méthode entraînent une légère pénalité de performances si le compilateur décide de ne pas être en ligne.

  • La synchronisation et le multi-threading sont simples et efficaces. Java a été conçu pour être sensible aux threads depuis le début, et cela se voit. Les ordinateurs modernes disposent généralement de plusieurs cœurs, et comme le threading est intégré au langage, vous pouvez très facilement en profiter. Fondamentalement, une augmentation de vitesse supplémentaire de 100% à 300% par rapport au code C standard à un seul thread. Oui, le threading C et les bibliothèques soigneusement écrits peuvent battre cela, mais c'est beaucoup de travail supplémentaire pour le programmeur.

  • Les chaînes incluent la longueur: certaines opérations sont plus rapides. Cela bat en utilisant des chaînes délimitées par null (courant en C). Dans Java 7, Oracle a supprimé l'optimisation String.subString (), car les gens l'utilisaient bêtement et obtenaient des fuites de mémoire.

  • La copie de tableau est hautement optimisée. Dans les dernières versions, Java utilise l'assembleur réglé manuellement pour System.arraycopy. Le résultat est que dans les opérations arraycopy / memcopy-heavy, j'ai vu mon code battre l'équivalent en C avec des marges raisonnables.

  • Le compilateur JIT utilise intelligemment le cache L1 / L2 . Les programmes compilés à l'avance ne peuvent pas adapter leur code en temps réel au processeur et au système spécifiques sur lesquels ils s'exécutent. JIT fournit des transformations de boucle très efficaces de cette façon.

Quelques autres faits historiques ont contribué à la réputation de «Java est lent»:

  • Avant la compilation JIT (Java 1.2 / 1.3), le langage était uniquement interprété, non compilé, et donc très lent.
  • La compilation JIT a mis du temps à devenir efficace (améliorations majeures à chaque version)
  • Le chargement de classe est devenu beaucoup plus efficace au fil des ans. Il était auparavant assez inefficace et lent au démarrage.
  • Le code Swing et UI n'utilisait pas très bien le matériel graphique natif.
  • Le swing est tout simplement horrible. Je blâme AWT et Swing pour la raison pour laquelle Java n'a jamais pris son envol pour le bureau.
  • Utilisation intensive de la synchronisation dans les classes de bibliothèque; des versions non synchronisées sont maintenant disponibles
  • Les applets prennent une éternité à se charger, en raison de la transmission d'un JAR complet sur le réseau et du chargement de la VM pour démarrer.
  • La synchronisation entraînait une forte pénalité de performances (cela a été optimisé avec chaque version de Java). La réflexion reste cependant coûteuse.
BobMcGee
la source
49
Object instantiation and object-oriented features are blazing fast to use (faster than C++ in many cases) because they're designed in from the beginning.et Collections are fast. Standard Java beats standard C/C++ in this area, even for most optimized C code.sont des affirmations sauvages non étayées par des preuves liées ici.
Sjoerd
8
@Sjoerd - Les affirmations ne sont guère sauvages - elles sont évidentes pour moi et devraient l'être pour quiconque comprend les différences dans l'architecture du système de mémoire par défaut en C / C ++ par rapport à Java. Vous pouvez faire beaucoup mieux encore si vous écrivez vos propres gestionnaires de mémoire (avec des éléments comme des listes libres, des pools de mémoire, etc.) ou si vous utilisez une bibliothèque qui implémente de tels.
Rex Kerr
15
@Rex Kerr - Pourquoi utiliser des gestionnaires de mémoire si vous pouvez utiliser par exemple la pile pour l'allocation?! Vous confondez l'allocation de mémoire de tas avec l'instanciation d'objet.
Sjoerd
20
@Rex Kerr - En gros, vous prétendez que parce que tout en Java implique l'allocation de mémoire sur le tas, et parce que l'allocation de Java sur le tas en Java est plus rapide que celle de C ++, tout en Java est plus rapide. Voici quelques nouveautés pour vous: en C ++, vous pouvez vous passer de mémoire sur le tas dans de nombreux cas!
Sjoerd
10
@Sjoerd - Où ai-je dit que tout en Java est plus rapide? Lisez simplement ce que j'ai dit. J'ai dit ce que je voulais dire et j'ai déjà répondu à tout ce que vous avez dit dans votre dernier commentaire.
Rex Kerr
49

Au départ, Java n'était pas particulièrement rapide, mais il n'est pas trop lent non plus. Ces jours-ci, Java est très rapide. Des personnes à qui j'ai parlé, l'impression que Java est lent vient de deux choses:

  1. Temps de démarrage lent de la VM. L'implémentation précoce de Java a pris beaucoup de temps pour démarrer et charger les bibliothèques requises et l'application par rapport aux applications natives.

  2. Interface utilisateur lente. Early Swing était lent. Cela n'a probablement pas aidé la plupart des utilisateurs de Windows à trouver le Metal L&F par défaut moche non plus.

Compte tenu des points ci-dessus, il n'est pas étonnant que les gens aient l'impression que «Java est lent».

Pour les utilisateurs ou développeurs habitués à développer des applications natives, voire Visual Basic applications , ces deux points sont la chose la plus visible dans une application, et c'est la première impression que vous obtiendrez d'une application (à moins qu'il ne s'agisse d'une application non-GUI dans laquelle cas seul le 1. s'applique.).

Vous ne convaincrez pas un utilisateur qu '«il exécute le code très rapidement» lorsque l'application prend 8 secondes pour démarrer par rapport à son ancienne application Visual Basic qui démarre immédiatement - même si l'exécution du code et l'heure de démarrage peuvent ne pas être connectées du tout.

Ruiner la première impression est un excellent moyen de lancer des rumeurs et des mythes. Et les rumeurs et les mythes sont difficiles à tuer.

Bref, Java n'est pas lent. Les personnes ayant la "attitude lente de Java" sont basées sur les premières impressions de Java il y a plus de 10 ans.

nos
la source
3
Java était très lent il y a quelques années, mais dans les tests de référence récents, il fonctionne presque aussi vite que C / C ++ et dans certaines situations, il fonctionne plus rapidement.
ChadNC
23
Les applications Java sur OSX 10.6 sur mon Macbook démarrent beaucoup plus lentement que les applications écrites en Objective-C. Quelle preuve de temps de démarrage rapide?
Zan Lynx le
2
La décompression n'est absolument pas un problème de performances. Mon ordinateur en 1992 décompressait les exécutables lors du démarrage de programmes, ce qui améliorait les performances par rapport au chargement d'un fichier plus long à partir du disque dur. La disparité entre le processeur et le disque dur s'est considérablement accrue au fil des années. Cependant, il y a un problème avec l'utilisation du format d'archive zip pour rt.jar (pourquoi? !!!) et les fichiers de classe contenus ne sont pas liés (fous !!).
Tom Hawtin - tackline
5
@Zan: notez que la JVM pour Mac OS X est écrite (ou au moins adaptée) par Apple. Sun a investi un certain temps pour accélérer les temps de démarrage sur les plates-formes prises en charge (Windows, Linux et Solaris), mais ils ne pouvaient pas le faire pour Mac OS x (car ils ne maintiennent pas ce port). Il se peut que Mac ne puisse pas / n'ait pas appliqué / porter toutes ces optimisations sur Mac OS X.
Joachim Sauer
1
Je ne considère pas que java est lent (je connais un créateur de jeux qui en fait des jeux); juste mauvais pour des raisons d'interface utilisateur. Pas une seule application Java "ordinaire" que j'ai vue n'a une interface utilisateur décente et complètement fonctionnelle.
RCIX
40

Après avoir lu une page pleine de commentaires disant que Java n'est pas lent, je dois juste répondre avec une opinion différente.

La lenteur d'une langue dépend beaucoup de ce que vous attendez de «rapide». Si vous considérez que C # est rapide, Java l'est sûrement aussi. Si votre domaine problématique est lié aux bases de données ou au traitement en semi-temps réel, Java est sûrement assez rapide aussi. Si vous souhaitez faire évoluer votre application en ajoutant plus de matériel, Java est probablement rapide pour vous. Si vous considérez qu'une accélération de facteur constant sur une échelle de 5 à 10 ne vaut souvent pas la peine, vous considérez probablement Java comme rapide.

Si vous effectuez des calculs numériques sur de grands ensembles de données ou si vous êtes lié à un environnement d'exécution, où les ressources du processeur sont limitées, où une accélération constante à l'échelle de 5 à 10 serait énorme. Même une accélération de 0,5 peut signifier une réduction de 500 heures pour le calcul. Dans ces cas, Java ne vous permet tout simplement pas d'obtenir ce dernier mètre de performances et vous considérez probablement Java comme lent.

Sami
la source
2
d'accord, et +1 sur tout le post parce que vous présentez un point valide, cependant, C ++ par exemple a la réputation différente d'être difficile à déboguer et facile à faire sauter toute votre jambe, mais j'ai rarement entendu dire que C ++ était aussi lent comme j'ai entendu parler de java.
Stefano Borini
33

Vous semblez poser deux questions assez différentes:

  1. Java est-il vraiment lent, et si oui, pourquoi?
  2. Pourquoi Java est-il perçu comme lent, même s'il est plus rapide que de nombreuses alternatives?

La première de ces questions est plus ou moins une question du genre «combien de temps dure une corde». Cela revient à votre définition de «lent». Comparé à un interpréteur pur, Java est extrêmement rapide. Comparé à d'autres langages qui sont (normalement) compilés en une sorte de bytecode, puis compilés dynamiquement en code machine (par exemple C # ou autre chose sur .NET), Java est à peu près sur un pied d'égalité. Comparé aux langages qui sont normalement compilés en code machine pur, et qui ont (souvent de grandes) équipes de personnes qui ne travaillent que sur l'amélioration de leurs optimiseurs (par exemple C, C ++, Fortran, Ada), Java fait plutôt bien sur un certain nombre de choses, mais dans l'ensemble a tendance à être au moins un peu plus lent.

Une grande partie de cela est principalement liée à l'implémentation - fondamentalement, cela se résume au fait qu'un utilisateur attend pendant qu'un compilateur dynamique / JIT s'exécute, donc à moins que vous n'ayez un programme qui s'exécute pendant un certain temps pour commencer, c'est difficile de justifier que le compilateur passe beaucoup de temps sur des optimisations difficiles. Par conséquent, la plupart des compilateurs Java (et C #, etc.) ne mettent pas beaucoup d'efforts dans des optimisations vraiment difficiles. Dans de nombreux cas, il s'agit moins de savoir quelles optimisations sont effectuées que de savoir où elles sont appliquées. De nombreux problèmes d'optimisation sont NP complets, de sorte que le temps qu'ils prennent augmente rapidement avec la taille du problème attaqué. Une façon de garder le temps dans la raison est de n'appliquer l'optimisation qu'à quelque chose comme une seule fonction à la fois. Quand il n'y a que le développeur qui attend le compilateur, vous pouvez vous permettre de prendre beaucoup plus de temps et d'appliquer la même optimisation à des morceaux beaucoup plus volumineux du programme. De même, le code de certaines optimisations est assez poilu (et peut donc être assez gros). Encore une fois, comme l'utilisateur attend pendant le chargement de ce code (et le temps de démarrage de la JVM est souvent un facteur important dans le temps global), la mise en œuvre doit équilibrer le temps gagné à un endroit par rapport à la perte à un autre - et compte tenu du peu de code bénéficie des optimisations épineuses, il est généralement plus avantageux de garder la JVM petite.

Un deuxième problème est qu'avec Java, vous obtenez souvent une solution plus ou moins «universelle». Par exemple, pour de nombreux développeurs Java, Swing est essentiellement la seule bibliothèque de fenêtrage disponible. Dans quelque chose comme C ++, il existe littéralement des dizaines de bibliothèques de fenêtrage, de frameworks d'application, etc., chacun avec son propre ensemble de compromis entre facilité d'utilisation vs exécution rapide, aspect cohérent vs aspect natif, etc. Le seul vrai problème est que certains (par exemple Qt) peuvent être assez chers (au moins pour un usage commercial).

Troisièmement, beaucoup de code écrit en C ++ (et encore plus en C) est simplement plus ancien et plus mature. Beaucoup de ceux-ci contiennent un noyau de routines écrites il y a des décennies, alors que passer plus de temps à optimiser le code était un comportement normal et attendu. Cela a souvent un réel avantage dans un code plus petit et plus rapide. C ++ (ou C) obtient le crédit pour le code étant petit et rapide, mais c'est vraiment beaucoup plus un produit du développeur et des contraintes du moment où le code a été écrit. Dans une certaine mesure, cela conduit à une prophétie auto-réalisatrice - lorsque les gens se soucient de la vitesse, ils choisissent souvent C ++ parce qu'il a cette réputation. Ils consacrent plus de temps et d'efforts à l'optimisation et une nouvelle génération de code C ++ rapide est écrite.

Pour résumer, l'implémentation normale de Java rend au mieux une optimisation maximale problématique. Pire encore, là où Java est visible , des éléments tels que les boîtes à outils de fenêtrage et le temps de démarrage de la JVM jouent souvent un rôle plus important que la vitesse d'exécution du langage lui-même de toute façon. Dans de nombreux cas, C et C ++ obtiennent également du crédit pour ce qui est vraiment le produit de simplement travailler plus dur à l'optimisation.

Quant à la deuxième question, je pense que c'est en grande partie une question de nature humaine au travail. Quelques fanatiques font des déclarations plutôt exagérées sur la rapidité aveuglante de Java. Quelqu'un l'essaie et constate que même un programme trivial prend quelques secondes pour démarrer, et se sent lent et maladroit lorsqu'il s'exécute. Peu de gens prennent probablement la peine d'analyser les choses pour se rendre compte qu'une grande partie de cela est le temps de démarrage de la JVM, et le fait que lorsqu'ils essaient pour la première fois, aucun code n'a encore été compilé - une partie du code est en cours d'interprétation, et certains sont compilés en attendant. Pire encore, même s'il fonctionne assez vite, l'aspect et la convivialité sembleront généralement étrangers et maladroits à la plupart des utilisateurs, donc même si des mesures objectives montraient des temps de réponse rapides, cela semblerait toujours maladroit.

Les ajouter ensemble conduit à une réaction assez simple et naturelle: que Java est lent, laid et maladroit. Étant donné le battage médiatique qui dit que c'est vraiment rapide, il y a une tendance à réagir de manière excessive et à conclure que c'est horriblement lent, au lieu d'un (plus précis) "légèrement plus lent, et cela surtout dans des circonstances spécifiques." C'est généralement le pire pour un développeur qui écrit les premiers programmes dans le langage. L'exécution d'un programme "hello world" dans la plupart des langages semble instantanée, mais en Java, il y a une pause facilement perceptible au démarrage de la JVM. Même un interpréteur pur qui fonctionne beaucoup plus lentement sur des boucles serrées et qui apparaîtra souvent plus vite pour un code comme celui-ci, simplement parce qu'il peut être chargé et commencer à s'exécuter un peu plus tôt.

Jerry Coffin
la source
16

Ce sont des informations obsolètes des premiers jours (du milieu à la fin des années 1990) de Java. Chaque version majeure de Java a introduit des accélérations significatives par rapport à la version précédente. Avec la fusion apparemment d'Oracle de JRockit avec la JVM de Sun pour Java 7, cette tendance devrait se poursuivre.

Comparé à de nombreux autres langages modernes populaires (Python, Ruby, PHP), Java est en fait beaucoup plus rapide pour la plupart des utilisations. Cela ne correspond pas tout à fait au C ou au C ++, mais pour de nombreuses tâches, il est assez proche. Les véritables problèmes de performances devraient concerner la quantité de mémoire utilisée.

Dan Dyer
la source
14

Le principal coupable du "long temps de démarrage" est la liaison dynamique. Une application Java se compose de classes compilées. Chaque classe fait référence à d'autres classes (pour les types d'arguments, les invocations de méthodes ...) par nom . La machine virtuelle Java doit examiner et faire correspondre ces noms au démarrage. Il le fait progressivement, ne faisant que les pièces dont il a besoin à un moment donné, mais c'est encore du travail à faire.

Dans une application C, cette phase de liaison a lieu à la fin de la compilation. C'est lent, surtout pour les grosses applications, mais seul le développeur le voit. La liaison produit un fichier exécutable que le système d'exploitation doit simplement charger dans la RAM "tel quel".

En Java, la liaison se produit à chaque fois que l'application est exécutée. D'où le long temps de démarrage.

Diverses optimisations ont été appliquées, y compris des techniques de mise en cache, et les ordinateurs deviennent plus rapides (et ils deviennent «plus rapides» que les applications «grossissent»), de sorte que l'importance du problème a beaucoup diminué ces derniers temps; mais le vieux préjugé demeure.

En ce qui concerne les performances par la suite, mes propres tests de performance sur les calculs compacts avec accès aux tableaux (principalement des fonctions de hachage et d'autres algorithmes cryptographiques) montrent généralement que le code C optimisé est environ 3 fois plus rapide que le code Java; parfois C n'est que 30% plus rapide que Java, parfois C peut être 4x plus rapide, selon l'algorithme implémenté. J'ai vu un facteur 10x lorsque le code "C" était en fait un assemblage pour l'arithmétique de gros entiers, en raison des opcodes de multiplication 64x64-> 128 que le processeur offre mais que Java ne peut pas utiliser car son type entier le plus long est le 64 bits long. Ceci est un cas de pointe. Dans des conditions pratiques, les considérations d'E / S et de bande passante mémoire empêchent le code C d'être vraiment trois fois plus rapide que Java.

Thomas Pornin
la source
Hmm ... Je pensais que la plupart des bibliothèques C étaient également liées dynamiquement de nos jours. Ou parlez-vous de quelque chose de différent?
Sean McMillan
4
@Sean: la liaison dynamique pour C se produit pour les "symboles externes": les fonctions qui sont utilisées dans une DLL et définies dans une autre. Une application C typique utilisera une douzaine de DLL. Pour Java, la liaison dynamique se produit pour toutes les méthodes de toutes les classes: il y en a des milliers dans une application Java typique (y compris la bibliothèque standard). Dans le monde C, la plupart des liens (tous les liens qui ne traversent pas une limite de DLL) sont résolus au moment de la compilation, seule une petite proportion reste à faire au moment de l'exécution.
Thomas Pornin
14

Java est définitivement lent, en particulier pour le travail quantitatif.

J'utilise une combinaison de R , Python et C / C ++ avec des bibliothèques ATLAS multithread optimisées . Dans chacune de ces langues, je peux multiplier par matrice une matrice de 3000 par 3000 de doubles avec elle-même en environ 4 secondes. En utilisant Colt et Parallel Colt en Java, la même opération prend 185 secondes! Étonnant bien que ces bibliothèques java soient de nature parallèle.

Dans l'ensemble, le Java pur ne convient donc pas au travail quantitatif. Jblas semble être la meilleure bibliothèque d'algèbre linéaire pour Java car elle utilise ATLAS.

Ma machine est un HP Core 2 Duo avec 3 Go de RAM. J'utilise Ubuntu 10.04 64 bits (Lucid Lynx).

Hamaad Shah
la source
Suite à mon commentaire ci-dessus, j'ai effectué la même opération de multiplication de matrice en utilisant JAMA et cela a pris environ 50 secondes. Encore trop lent par rapport aux autres langues.
Hamaad Shah
7
Combien de temps a pris Java lorsque vous avez effectué la multiplication dans les libraires appelées via JNI. Étant donné que tout ce que vous pouvez faire en C / C ++, vous pouvez le faire avec JNI (ajoutez quelques centaines de mnano-secondes), la marge est relativement petite. Je suppose que votre multiplication matricielle R et Python n'a pas été écrite en R ou Python, juste appelée à partir de ces langages.
Peter Lawrey
2
Par curiosité, avez-vous effectué un profilage pour identifier si vous avez un hotspot dans votre code (conversion de type / autoboxing)?
Thorbjørn Ravn Andersen
10

Pour la plupart des gens qui interagissent avec lui, Java est lent. Nous avons tous vu cette tasse de café tourner sur notre navigateur avant qu'une applet n'apparaisse. Il faut un certain temps pour démarrer la JVM et télécharger les binaires de l'applet, ce qui a un impact sur l'expérience utilisateur d'une manière qui est remarquée.

Cela n'aide pas que la lenteur de la rotation de la JVM et du téléchargement de l'applet soit clairement marquée avec une tasse à café Java, de sorte que les gens associent l'attente à Java. Lorsque Flash prend beaucoup de temps à se charger, la marque du message "chargement" est spécifiée par le développeur Flash, donc les gens ne blâment pas la technologie Flash dans son ensemble.

Tout cela n'a rien à voir avec les performances de Java sur un serveur, ni avec les nombreuses autres façons dont Java est utilisé en dehors du navigateur. Mais c'est ce que les gens voient et ce que les développeurs non Java se souviennent lorsqu'ils pensent à Java.

Spike Williams
la source
9

Java a la réputation d'être lent parce qu'il était lent. Les premières versions de Java avaient une compilation Just In Time non ou plutôt médiocre. Cela signifiait que le code, bien que bytecode, était en cours d'interprétation, donc même pour les opérations les plus simples (comme l'ajout de deux entiers), la machine devait faire toutes sortes de comparaisons et de déréférences de pointeurs et d'appels de fonctions. Le compilateur JIT n'a cessé de s'améliorer; maintenant, c'est au point où si j'écris du code C ++ négligemment et du code Java négligemment, Java surclassera parfois C ++ parce que le compilateur JIT se rend compte que j'ai un déréférencement de pointeur inutile et s'en chargera pour moi.

Si vous voulez voir à quel point la compilation JIT fait la différence, consultez les benchmarks interprétés et non interprétés au Computer Languages ​​Benchmark Game . (Pidigits utilise une bibliothèque externe pour faire tous les calculs, afin que le benchmark ne change pas; les autres montrent une accélération 6-16x!)

Alors, c'est la raison principale. Il existe une variété d'autres raisons moins importantes qui n'ont pas aidé les choses: à l'origine, le temps de démarrage de Java était lent (maintenant corrigé); les applications Web en Java prennent beaucoup de temps à télécharger (ce qui est encore moins vrai maintenant avec le haut débit largement accessible et avec de grandes choses comme des films); l'interface utilisateur Swing n'a pas été (et n'est toujours pas) écrite avec les performances à l'esprit, elle est donc beaucoup moins dynamique que ses équivalents en C ++ par exemple.

Rex Kerr
la source
6

Java était lent, à l'époque. Il est devenu beaucoup plus rapide, grâce à quelques générations d'améliorations des performances . La dernière fois que j'ai entendu dire, il est généralement à moins de 10% de la vitesse C # - parfois plus rapide, parfois plus lente.

Le démarrage de l'applet Java est encore lent car vous devez démarrer une JVM entière, qui doit charger toutes ses classes. Un peu comme démarrer un autre ordinateur. Une fois que la JVM démarre, c'est assez rapide, mais le démarrage est généralement ce dont les gens se souviennent.

De plus, il y a au moins quelques personnes qui ne croiront jamais en la viabilité de Java.

Kaleb Brasee
la source
1
Le démarrage de la JVM est encore beaucoup plus lent que celui du CLR, malheureusement. C'est parce que Sun a traîné les pieds de la pire façon en sortant Java 7, nous sommes donc bloqués avec des correctifs incrémentiels pour le Java 6 de 4 ans .
BobMcGee
3
Wow, Java 6 a 4 ans ??? Oui, je suppose (si vous comptez la version bêta). Je me sens toujours nouveau - je viens d'arrêter d'utiliser la 1.4 au travail.
Kaleb Brasee le
Java 1.4 est utilisable, mais un peu sucktastic, puisque 1.5 et 1.6 ont ajouté beaucoup d'augmentations de performances et de sucre syntaxique. Les optimisations Bounds-check et System.arraycopy ont été introduites depuis lors. Il y avait donc beaucoup d'améliorations de la synchronisation. Je pense qu'il est juste de dire que 1.4 est vraiment lent.
BobMcGee
LOL, je sais - chaque fois que je dois itérer manuellement ou utiliser un tableau au lieu d'une liste générique, je veux diviser mon ordinateur portable en deux ... IBM a en fait Java 5 disponible sur WAS 6.1 depuis des années, mais je ' J'ai été bloqué sur WAS 6.0: (J'utilise Java 5/6 depuis sa sortie pour mes propres affaires, mais je suis juste limité par les anciennes versions de serveur au travail. Il y a des améliorations à deux chiffres des performances en pourcentage de la 1.4 aux dernières versions pour beaucoup de choses, et je les attend avec impatience.
Kaleb Brasee
6

Stefano:

Je suis avec Java depuis le début, donc de mon point de vue, la réputation d'être lente a été créée par des interfaces graphiques non réactives et lentes (AWT, puis Swing) et dans les applets probablement à cause des temps de démarrage lents supplémentaires du VM.

Java a stipulé et promu de nombreuses recherches dans le domaine des VM, et il y a eu pas mal d'améliorations, y compris le ramasse-miettes (vous pouvez en fait régler beaucoup de choses; cependant, je vois souvent des systèmes où seules les valeurs par défaut sont utilisées) et hotspot l'optimisation (qui au début et probablement encore plus efficace côté serveur).

Java au niveau du backend et du calcul n'est pas si lent. Colt est l'un des meilleurs exemples:

La dernière version stable de Colt brise la barrière de 1,9 Gflop / s sur JDK ibm-1.4.1, RedHat 9.0, 2x [email protected] GHz.

Il y a beaucoup de choses en dehors de Java traditionnel qui devraient être prises en compte, comme Java en temps réel ou des mécanismes spéciaux pour améliorer la vitesse comme Javolution , ainsi que la compilation Ahead-Of-Time (comme gcj). En outre, il existe des IC qui peuvent exécuter directement le Bytecode Java, comme par exemple celui qui se trouve dans les iPhones et iPods ARM Jazelle actuels .

Je pense que généralement aujourd'hui c'est une décision politique (comme pas de support Java sur l'iPhone / iPod), et une décision contre Java en tant que langage (car beaucoup pensent que c'est trop verbeux).

Cependant, il existe de nos jours de nombreux autres langages pour la machine virtuelle Java (par exemple Python, Ruby, JavaScript, Groovy, Scala, etc.) qui peuvent être une alternative.

Personnellement, je continue de l'apprécier en tant que plate-forme flexible et fiable, avec d'excellents outils et une excellente disponibilité de bibliothèque, qui permet de travailler avec tout, du plus petit périphérique (par exemple JavaCard) aux plus grands serveurs.

Dieter
la source
Ok, donc une autre mauvaise réputation est venue du toolkit GUI. Bien sûr, je suppose que, puisque la JVM moderne utilise des widgets natifs, ils se connectent aux bibliothèques du système d'exploitation, non? ou utilisent-ils AWT / Swing pour rendre le même aspect et la même sensation de la plate-forme hôte?
Stefano Borini
Stefano: Swing est en fait basé sur l'idée d'un rendu universel non natif des widgets, donc votre hypothèse est un peu fausse. Il s'agit en effet d'un mécanisme «pluggable look & feel» qui permet aux composants Swing d'émuler l'apparence des composants natifs. Si vous cherchez quelque chose comme ça, vous voudrez peut-être consulter SWT ( eclipse.org/swt ), qui se connectera effectivement au système d'exploitation natif et utilisera des widgets natifs utilisant JNI (ce qui est considéré comme un goulot d'étranglement).
Dieter
Java2D (utilisé pour Swing) est très rapide de nos jours, et l'utilisation de widgets natifs (SWT) n'offre aucun avantage en termes de performances. Du moins, c'est ce que j'ai lu quand je décidais d'apprendre le Swing ou le SWT il y a 6 mois.
Luigi Plinge du
4

Un marteau est beaucoup plus lent à étaler la pâte que de nombreux autres outils. Ne rend pas le marteau "plus lent", ni moins utile pour les tâches pour lesquelles il est conçu.

En tant que langage de programmation général, Java est à égalité avec beaucoup (sinon la plupart) pour un large éventail de tâches de programmation. Il existe des tests spécifiques et triviaux pour lesquels Java ne surpassera pas les solutions codées à la main dans des langages moins sophistiqués, qui sont «plus proches du métal».

Mais lorsqu'il s'agit d '«applications du monde réel», Java est souvent le bon outil. Maintenant, cela dit, rien n'empêchera les développeurs de créer une solution lente en utilisant N'IMPORTE QUEL outil. La mauvaise utilisation de l'outil est un problème bien connu (il suffit de regarder les réputations de PHP et de VB). Cependant, la conception et la syntaxe (principalement) propres de Java font beaucoup pour réduire les abus.

mobiGeek
la source
3

Java est un langage de haut niveau et sa réputation de nos jours est d'avoir des performances comparables à celles d'autres langages comparables de haut niveau.

  1. Il a une sémantique de liaison dynamique . Par rapport au C ++ où les méthodes non virtuelles sont compilées sous forme d'appels de fonction, même le meilleur compilateur Java au monde doit produire du code moins efficace. Mais c'est aussi une sémantique plus propre et de plus haut niveau.

  2. Je ne me souviens pas des détails, mais j'ai entendu dans les premiers jours de Java qu'il y avait un mutex par objet Java, à acquérir et à libérer par chaque méthode. Cela tend à le rendre mieux adapté à la concurrence, bien que malheureusement, juste un mutex par objet ne vous protège pas des courses, des blocages ou de toutes les mauvaises choses qui peuvent survenir dans les programmes concurrents. Cette partie, si elle est vraie, est un peu naïve, mais elle est venue de bonnes intentions. N'hésitez pas à me renseigner sur les détails si vous en savez plus sur cet aspect.

  3. Une autre façon dont Java est un langage de haut niveau consiste à avoir Garbage-Collection . Le nettoyage de la mémoire peut être plus lent que mallocet freepour les programmes qui allouent à la fois toute la mémoire dont ils ont besoin et travaillent avec. Le problème est que, dans les langages qui n'ont pas de récupération de place, les programmeurs ont tendance à n'écrire que des programmes qui allouent toute la mémoire dont ils ont besoin à la fois et échouent s'il s'avère qu'une constante de taille maximale arbitraire a été dépassée. Donc, la comparaison est des pommes aux oranges. Lorsque les programmeurs font l'effort d'écrire et de déboguer des programmes avec une allocation dynamique de structures chaînées dans des langages non GC, ils constatent parfois que leurs programmes ne sont pas plus rapides que dans un langage GC, carmalloc etfreene sont pas gratuits! Ils ont aussi des frais généraux ... De plus, ne pas avoir de GC oblige à spécifier qui libère quoi, et le fait de devoir spécifier qui libère quoi à son tour vous oblige parfois à faire des copies - lorsque plusieurs fonctions vont avoir besoin des données et que l'on ne sait pas lesquelles l'utilisera en dernier - alors que la copie n'aurait pas été nécessaire dans un langage GC.

Pascal Cuoq
la source
1. Probablement pas vrai avec HotSpot. 2. Uniquement si vous marquez la méthode comme synchronisée.
Winston Ewert
1
1. Le compilateur n'optimise pas le code, mais la JVM est assez intelligente pour déterminer dynamiquement qu'une ou deux méthodes virtuelles sont généralement appelées et peuvent les appeler de manière statique ou même en ligne. Je suis presque sûr que C ++ ne peut pas intégrer de méthodes virtuelles. 2. Chaque objet Java possède un verrou. Il a une petite surcharge (environ un octet) sur chaque objet mais a peu d'impact s'il n'est pas utilisé. 3. En Java, vous pouvez allouer à la fois tous les objets dont vous avez besoin. Cela peut vous donner une application qui ne GC pas toute la journée. ;) Le GC de Java est implicitement multi-thread, ce qui nécessite des libraires spéciales en C ++.
Peter Lawrey
C ++ peut intégrer des appels virtuels, mais Java peut le faire dans plus de cas, et est également plus efficace avec l'optimisation des sites d'appels mégamorphiques.
Piotr Kołaczkowski
2

Au milieu des années 90, lorsque Java est devenu populaire, C ++ était le langage dominant et le Web était encore assez récent. En outre, les JVM et GC étaient des concepts relativement nouveaux dans le développement grand public. Les premières machines virtuelles Java étaient un peu lentes (par rapport au C ++ fonctionnant sur du métal nu) et souffraient également de longues pauses de récupération de place, ce qui a conduit à une réputation de lenteur de Java.

Ken Liu
la source
était-ce dû à la technologie derrière le GC? Je sais qu'ils ont des stratégies (comme des couches générationnelles pour les objets) pour être plus efficaces dans la phase GC. Quelle était la stratégie à l'époque?
Stefano Borini
1
Expert IANA JVM, mais je pense qu'à l'époque il y avait un seul algorithme de marquage / balayage fileté utilisé pour GC, ce qui obligeait l'ensemble de la JVM à faire une pause pendant que le GC était en cours d'exécution. De nos jours, il existe des marques / balayages simultanés et de nombreuses autres améliorations de performances dans la JVM.
Ken Liu
2
Les algorithmes GC modernes sont bien, mais je pense que la plus grande amélioration a été JIT.
Pascal Thivent
1

De nombreuses applications de bureau Java (ces temps-ci: des choses comme Eclipse) ont une mauvaise réactivité de l'interface graphique, probablement en raison de la consommation élevée de mémoire et du fait que le chargeur de classe peut faire beaucoup d'E / S. Cela s'améliore mais était pire il y a quelques années.

Beaucoup (la plupart) des gens aiment faire des généralisations alors ils disent que "Java est lent" parce qu'ils perçoivent que les applications sont lentes lorsqu'elles interagissent avec elles.

Wojciech Kaczmarek
la source
pensez-vous que la consommation élevée de mémoire provient de l'outil ou des bibliothèques java?
Stefano Borini
Dans le cas d'Eclipse - de l'infrastructure Eclipse elle-même. Idem pour les interfaces graphiques "lourdes" du passé (JBuilder si je me souviens bien). J'ai le sentiment instinctif que c'est parce que de nombreux objets standard sont nécessaires pour utiliser une architecture de plugin (comme Eclipse) dans un langage typé statiquement. Emacs a également des plugins et sa consommation de mémoire est 10 à 20 fois inférieure à Eclipse lors du codage typique. Le code Lisp d'Emacs est compilé en bytecode et chargé dans l'instance emacs, puis exécuté - similaire au chargeur de classe Java. Je suppose qu'en Java, il existe des tonnes d'objets intermédiaires instanciés pour permettre une certaine connectivité.
Wojciech Kaczmarek
1

Le problème majeur avec les applications Java est qu'elles sont énormes en raison de la grande taille de la bibliothèque d'exécution stock. Les programmes énormes remplissent beaucoup de mémoire et ont tendance à changer, ce qui signifie qu'ils deviennent lents.

La raison pour laquelle la JVM Sun est volumineuse est qu'elle possède un très bon interpréteur de code d'octet qui fonctionne en gardant une trace de beaucoup de choses. Cela signifie beaucoup de données, ce qui signifie de la mémoire.

Vous voudrez peut-être regarder la machine virtuelle jamvm qui est un interpréteur raisonnablement rapide (pas de code natif) et très petit. Il démarre même rapidement.

Thorbjørn Ravn Andersen
la source
1

Comme le dit Pascal, Java est comparable à d'autres langages de haut niveau. Cependant, comme quelqu'un qui travaillait avec les JVM d'origine sur Windows 98 , à l'époque le niveau d'abstraction fourni par la machine virtuelle Java était, dirons-nous, pénible.

Fondamentalement, c'est une émulation logicielle avec peu ou pas d'optimisation que nous tenons pour acquis aujourd'hui dans la JVM.

caskey
la source
0

Les gens trottent normalement la ligne «c'est interprété». Parce qu'il était une fois, c'était le cas, et la mauvaise presse est transmise par des gens qui ont jeté Java comme «trop lent» et qui ne sont jamais revenus pour tester les nouvelles versions.

Ou peut-être que «les gens sont des idiots» est une meilleure réponse.

Monsieur Boy
la source
0

Je pense qu'un jour, peut-être pas dans un avenir trop proche, les langages compilés JIT surpasseront les langages compilés dans tous les aspects (enfin, peut-être pas le temps de démarrage / la consommation de mémoire) en raison du fait que les compilateurs JIT peuvent faire un usage intensif du runtime comportement et la plate-forme sur laquelle ils fonctionnent.

méthode d'aide
la source
6
Je pense que ce que vous voulez dire, c'est que le code compilé par JIT (non interprété) battra le code AoT. L'interprétation sera toujours plus lente que l'exécution de code compilé. C'est pourquoi les compilateurs JIT sont utilisés. Le hic: il y a peu de différence entre un compilateur à l'avance et un compilateur JIT en termes de sortie, sauf qu'un compilateur JIT doit compiler plus rapidement et peut utiliser les informations d'exécution pour indiquer ses optimisations. Les compilateurs AoT spécifiques à la plate-forme avec des optimisations spécifiques à la plate-forme battront presque toujours JIT car il n'y a pas de limite au temps qu'ils consacrent à l'optimisation.
BobMcGee
Merci pour la réponse, je n'ai jamais pensé au peu de temps dont disposent les compilateurs JIT.
helpermethod
vous voulez dire, quelque chose comme l'optimisation adaptative hotspot?
Stefano Borini
2
@BobMcGee: Très bien. Un programme C ++ peut être construit pour s'exécuter lentement avec des commentaires de profil pour toutes ses opérations. Ensuite, le compilateur est libre de reconstruire une version très rapide en utilisant une demi-heure de temps CPU et 2 Go de RAM. Un JIT qui ferait cela ferait partir les utilisateurs.
Zan Lynx du
1
Le temps de compilation JIT est négligeable pour les applications de longue durée comme les serveurs. AOT avec PGO est plus limité que JIT pour au moins 2 raisons. Premièrement, la plupart des différences de performances sont obtenues grâce à des optimisations légères. Comparez gcc -O2 à gcc -O3. La plupart du temps, il n'y a pas de différence , parfois -O3 peut être légèrement meilleur, parfois légèrement pire, mais je n'ai jamais connu de différence> 2x par rapport à cela. Deuxièmement, en utilisant AOT même avec PGO, vous ne pouvez que deviner quel sera le profil sur le site d'utilisation. Devinez faux, et vous êtes loin derrière le JIT. Et le profil réel peut être extrêmement dépendant de la configuration.
Piotr Kołaczkowski