web-dev-qa-db-fra.com

Une revue moderne de Java

Je programme depuis quelques années et j'ai commencé en Java, et en mon temps, j'ai trouvé de nombreuses sources différentes affirmant Java être un langage inférieur d'une manière ou d'une autre. Je ' Je sais bien que chaque langue a ses forces et ses faiblesses, mais beaucoup de choses que j'ai lues sur Java semblent datées.

La raison la plus souvent citée pour Java étant inférieur est qu'il est beaucoup plus lent que d'autres langages compilés nativement, comme C++ par exemple. Beaucoup de gens critiquent le concepteur de jeux Notch (qui a développé Minecraft) pour utiliser = Java en raison de son manque apparent dans le service des performances. Je sais Java était beaucoup plus lent à l'époque, mais il y a eu de nombreuses améliorations depuis, en particulier la compilation JIT .

Je voudrais avoir des opinions objectives sur Java en tant que langage aujourd'hui. Donc ma question comporte 4 parties.

  1. Performance.

    une. Comment la vitesse de Java se compare-t-elle aujourd'hui à C++?

    b. Serait-il possible de créer un titre AAA moderne en utilisant Java?

    c. Dans quels domaines est spécifiquement Java plus lent que C++, le cas échéant? (C'est-à-dire le calcul numérique, les graphiques ou tout simplement tout autour)

  2. Java est-il désormais considéré comme un langage compilé ou interprété?

  3. Quelles sont les principales lacunes de Java qui ont été corrigées depuis les premiers jours?

  4. Quelles sont les principales lacunes de Java qui n'ont pas encore été corrigées?

Éditer:

Juste pour des raisons de clarification, je ne fais pas cela Java vs C++, évidemment en moyenne c ++ sera un peu plus rapide que Java. J'ai simplement besoin de quelque chose pour comparer Java = à en termes de maturité en tant que langue à ce moment-ci. Puisque le c ++ existe depuis toujours, je pensais que je serais un bon point de comparaison.

58
Ryan Stull

une. Comment la vitesse de Java se compare-t-elle aujourd'hui à C++?

Difficile à mesurer. Il convient de noter qu'une grande partie de la vitesse d'une implémentation, son allocateur de mémoire, sont des algorithmes très différents en Java et C++. La nature non déterministe du collecteur rend extrêmement difficile l'obtention des données de performances significatives par rapport à la gestion de la mémoire déterministe de C++, car vous ne pouvez jamais être certain de l'état dans lequel se trouve le collecteur. Cela signifie qu'il est très difficile d'écrire une référence qui pourrait les comparer de manière significative. Certains modèles d'allocation de mémoire s'exécutent beaucoup plus rapidement avec un GC, certains fonctionnent beaucoup plus rapidement avec un allocateur natif.

Ce que je dirais cependant, c'est que le GC Java doit fonctionner rapidement dans chaque situation. Un allocateur natif , cependant, peut être remplacé par un plus approprié. J'ai récemment mis une question sur SO sur la raison pour laquelle un C # Dictionary pourrait s'exécuter (0,45 ms sur ma machine) par rapport à un équivalent std::unordered_map qui s'est exécuté (10 ms sur ma machine). Cependant, en remplaçant simplement l'allocateur et le hachage par des outils plus appropriés, j'ai réduit ce temps d'exécution à 0,34 ms sur ma machine, un trentième de l'exécution d'origine. Vous ne pourriez jamais espérer réaliser ce type d'optimisation personnalisée avec Java. Un excellent exemple de cas où cela peut faire une réelle différence est le filetage. Les bibliothèques de threads natives comme TBB fournissent des allocateurs de mise en cache de threads qui sont massivement plus rapides que les allocateurs traditionnels lorsqu'ils traitent de nombreuses allocations sur de nombreux threads.

Maintenant, beaucoup de gens parleront des améliorations du JIT et de la façon dont le JIT a plus d'informations. Bien sûr, c'est vrai. Mais ce n'est pas encore à distance proche de ce qu'un compilateur C++ peut tirer, car le compilateur a, comparativement, un temps et un espace infinis pour s'exécuter, du point de vue de l'exécution du programme final. Chaque cycle et chaque octet que le JIT passe à réfléchir à la meilleure façon d'optimiser votre programme est un cycle que votre programme ne passe pas à exécuter et ne peut pas utiliser pour ses propres besoins en mémoire.

En outre, il y aura toujours des moments où les optimisations du compilateur et du JIT ne pourront pas prouver certaines optimisations, en particulier dans le cas de choses comme l'analyse d'échappement. En C++, comme la valeur est de toute façon sur la pile , le compilateur n'a pas besoin de l'exécuter. De plus, il y a des choses simples, comme la mémoire contiguë. Si vous allouez un tableau en C++, vous allouez un seul tableau contigu. Si vous allouez un tableau en Java, ce n'est pas du tout contigu, car le tableau est uniquement rempli de pointeurs qui pourraient pointer n'importe où. Ce n'est pas seulement une surcharge de mémoire et de temps pour les doubles indirections, mais aussi des surcharges de cache. Ce genre de chose est là où la sémantique du langage de Java impose simplement qu'il doit être plus lent que le code C++ équivalent.

En fin de compte, mon expérience personnelle est que Java pourrait être environ la moitié de la vitesse de C++, en moyenne. Cependant, il n'y a en réalité aucun moyen de sauvegarder des déclarations de performances sans une suite de référence extrêmement complète, en raison de les algorithmes fondamentalement différents impliqués.

b. Serait-il possible de créer un titre AAA moderne en utilisant Java?

Je suppose que vous voulez dire "jeu", ici, et pas une chance. Tout d'abord, vous devez tout écrire vous-même à partir de zéro, car presque toutes les bibliothèques et infrastructures existantes ciblent C++. Bien que cela ne le rende pas impossible en soi, il pourrait certainement contribuer fortement à l'impossibilité. Deuxièmement, même les moteurs C++ peuvent difficilement tenir dans les contraintes de mémoire minuscules des consoles existantes - si des machines virtuelles Java existent même pour ces consoles - et les joueurs PC attendent un peu plus pour leur mémoire. La création de jeux AAA performants est déjà assez difficile en C++, je ne vois pas comment cela pourrait être réalisé en Java. Personne n'a jamais écrit un jeu AAA avec beaucoup de temps passé dans une langue non compilée. Plus que cela, il serait tout simplement extrêmement sujet aux erreurs. La destruction déterministe est essentielle lorsque vous traitez, par exemple, des ressources GPU - et en Java, vous devrez essentiellement les malloc () et les libérer ().

c. Dans quels domaines est spécifiquement Java plus lent que C++, le cas échéant? (C'est-à-dire le calcul numérique, les graphiques ou tout simplement tout autour)

J'irais certainement partout. La nature de référence forcée de tous les objets Java signifie que Java contient beaucoup plus d'indirection et de références que C++ - un exemple que j'ai donné plus tôt avec des tableaux, mais s'applique également à tous les objets membres, par exemple. Lorsqu'un compilateur C++ peut rechercher une variable membre en temps constant, un runtime Java Java doit suivre un autre pointeur. Plus vous avez d'accès , plus ça va être lent, et le JIT ne peut rien y faire.

Où C++ peut libérer et réutiliser un morceau de mémoire presque instantanément, dans Java vous devez attendre la collection, et j'espère que ce morceau n'est pas sorti du cache, et nécessitant par nature plus de mémoire signifie moins de performances de cache et de pagination. Ensuite, regardez la sémantique pour des choses comme la boxe et la décompression. En Java, si vous voulez référencer un int, vous devez l'allouer dynamiquement. C'est un gaspillage inhérent par rapport à la sémantique C++.

Ensuite, vous avez le problème des génériques. En Java, vous pouvez uniquement opérer sur des objets génériques via l'héritage d'exécution. En C++, les modèles ont littéralement zéro surcharge - quelque chose Java ne peut pas correspondre. Cela signifie que tout le code générique dans Java est intrinsèquement plus lent qu'un équivalent générique dans C++.

Et puis vous arrivez au comportement indéfini. Tout le monde déteste quand leur programme présente UB, et tout le monde souhaite qu'il n'existe pas. Cependant, UB permet fondamentalement des optimisations qui ne peuvent jamais exister en Java. Jetez un oeil à this post décrivant les optimisations basées sur UB. Ne pas définir de comportement signifie que les implémentations peuvent faire plus d'optimisations et réduire le code requis pour vérifier les conditions qui ne seraient pas définies en C++ mais définies en Java.

Fondamentalement, la sémantique de Java dicte qu'il s'agit d'un langage plus lent que C++.

Java est-il désormais considéré comme un langage compilé ou interprété?

Cela ne rentre vraiment dans aucun de ces groupes. Je dirais que géré est vraiment une catégorie distincte à part entière, même si je dirais que cela ressemble plus à un langage interprété qu'à un langage compilé. Plus important encore, il n'y a pratiquement que deux principaux systèmes gérés, la JVM et le CLR, et lorsque vous dites "géré", c'est suffisamment explicite.

Quelles sont les principales lacunes de Java qui ont été corrigées depuis les premiers jours?

La boxe et le déballage automatiques sont la seule chose que je sache. Les génériques résolvent certains problèmes , mais loin d'être nombreux.

Quelles sont les principales lacunes de Java qui n'ont pas encore été corrigées?

Leurs génériques sont très, très faibles. Les génériques de C # sont considérablement plus puissants - bien que, bien sûr, aucun des modèles ne soit tout à fait. La destruction déterministe est un autre manque majeur. Toute forme de lambda/fermeture est également un problème majeur - vous pouvez oublier une API fonctionnelle en Java. Et, bien sûr, il y a toujours le problème de la performance, pour les domaines qui en ont besoin.

62
DeadMG

Je commencerai par la condition qu'il est presque impossible pour quiconque de donner une opinion vraiment neutre sur les langages de programmation. Si vous connaissez suffisamment deux langues pour les commenter de manière significative, il est presque inévitable que vous préfériez l'une plutôt que l'autre. Comme avertissement, je préfère C++ à Java, ce qui influence sans aucun doute mes commentaires au moins dans une certaine mesure.

1a. Vitesse: la vitesse que vous obtenez à partir de C++ ou Java dépendra généralement moins du langage ou de son implémentation que de la compétence du ou des programmeurs qui l'utilisent. En fin de compte, C++ probablement can gagner pour la vitesse le plus souvent, mais les différences dans le code que vous écrivez sont vraiment importantes.
1b. Oui probablement. Dans le même temps, C++ est déjà bien établi, et je doute que la plupart des studios de jeux voient suffisamment d'avantages pour déranger le passage à Java.
1c. Une réponse approfondie à cette question pourrait probablement remplir un volume important. C++ fera généralement mieux avec des ressources plus limitées. Java profite davantage du fait (par exemple) de disposer de beaucoup de mémoire "disponible".
2. Une exécution lente et un ramassage des ordures lent seraient probablement les deux plus évidents. La bibliothèque de fenêtrage précoce (AWT) était assez maladroite - Swing était une amélioration majeure.
3. Verbosité. Manque de surcharge de l'opérateur. Utilisation de la collecte des ordures. Absence d'héritage multiple. Java Les génériques sont extrêmement limités par rapport aux modèles C++.

Je dois ajouter que certains (tous?) De ces inconvénients (en particulier l'utilisation du ramasse-miettes, mais aussi les autres) sont considérés par beaucoup comme des avantages de Java. La seule exception possible serait sa verbosité. La situation de verbosité s'améliore un peu lentement, mais vous ne voyez certainement pas très souvent Java gagner des concours de golf à code, et dans le code ordinaire, il a tendance à utiliser également beaucoup de code. I soupçonne qu'il y en a au moins quelques-uns qui le voient comme plus lisible et compréhensible, donc cela peut probablement être considéré comme un avantage également.

34
Jerry Coffin
  1. Concernant les performances;
    1. En vitesse d'exécution de code pur, Java est à peu près égal à C++ simple. Mais Java a tendance à utiliser beaucoup plus de mémoire - en partie parce qu'il est basé sur GC, en partie parce que sa conception met davantage l'accent sur la simplicité et la sécurité que sur l'efficacité. En raison de problèmes de cache, plus de mémoire se traduit par une vitesse plus faible. A lot inférieur par rapport au C++ hautement optimisé.
    2. Si vous supposez qu'un titre AAA doit fonctionner à la limite de ce qui est possible avec le matériel actuel, non. Du moins pas du côté client. Je serais prêt à parier que certains titres AAA utilisent déjà Java pour certaines parties de l'infrastructure backend.
    3. Tout ce que vous travaillez avec de grands ensembles de données et C++ peut être optimisé pour y accéder de manière compatible avec le cache.
  2. Il est compilé en bytecode et compilé en JIT lors de l'exécution. Compilé vs interprété est une dichotomie fausse et dépassée.
  3. & 4. Il y a trop de choses pour toutes les énumérer, et il y aura désaccord sur la plupart d'entre elles.
11
Michael Borgwardt

Tout d'abord, dans un certain contexte, mon C++ est très rouillé, donc la plupart de mes expériences avec Java se rapportent à mon expérience plus récente avec C #, qui est une comparaison beaucoup plus de pommes à pommes de toute façon.

1. Vitesse

une. Comment la vitesse de Java se compare-t-elle aujourd'hui à C++?

Je pense que cela est mieux répondu par la question SO Pourquoi est-ce que Java a la réputation d'être lent? mais je pense aussi que cela toute la question est colorée par le blog de Jeff Atwood, Gorilla vs SharkMerci à Péter et Christopher.

b. Serait-il possible de créer un titre AAA moderne en utilisant Java?

Cela dépend des priorités des développeurs et des compétences des développeurs. De plus, ce n'est pas une situation non plus/ou différente, différentes parties du titre peuvent nécessiter différentes choses différentes de la langue dans laquelle elles sont implémentées, conduisant à un environnement linguistique hétérogène.

J'ai vu un certain nombre de jeux mentionner récemment qu'ils chargent un environnement Python pendant qu'ils chargent et je soupçonne que chevaux pour les cours est une forte motivation si vous vous souhaitez obtenir votre titre à temps pour la période des fêtes (par exemple).

c. Dans quels domaines est spécifiquement Java plus lent que C++, le cas échéant? (C'est-à-dire le calcul numérique, les graphiques ou tout simplement tout autour)

Vous pouvez écrire du code peu performant dans n'importe quelle langue, mais certaines langues permettent de faire plus facilement de bons choix, tandis que d'autres sont plus susceptibles de vous laisser hisser par votre propre petard . Java appartient à la première catégorie, C++ appartient définitivement à la seconde.

Avec une grande puissance vient une grande responsabilité comme on dit (sans parler de la possibilité de complètement visser votre tas * 8 ').

2. Java est-il maintenant considéré comme un langage compilé ou un langage interprété?

Je ne peux pas dire ce que la plupart des gens le considèrent comme tel, mais beaucoup de gens connaissent la différence entre les langues compilées et interprétées, et ne vivaient pas dans une grotte depuis 20 ans. sachez également que le compilateur JIT ( Just-in-Time ) est une partie importante de l'écosystème Java, il est donc plus susceptible d'être considéré comme compilé de nos jours .

3. Quelles sont les principales lacunes de Java qui ont été corrigées depuis les premiers jours?

Je suis un converti assez récent en Java, donc j'ai peu de contexte sur la façon dont il a évolué. Mais il est intéressant de noter qu'il existe des livres comme Java: The Good Parts qui cherchent à orienter les gens vers les parties du langage qui devraient être préférées ces jours-ci et à éloigner les gens des zones qui sont, ou devraient être, obsolètes.

4. Quelles sont les principales lacunes de Java qui n'ont pas encore été corrigées?

À mon avis, un problème avec Java a été l'adoption lente de nouvelles fonctionnalités.

Étant venu à Java de C #, et en regardant à travers la page de comparaison Wikipedia , ce sont les choses qui se démarquent pour moi:

Les choses qui me manquent en Java, par rapport à C #

  • Propriétés , en particulier les propriétés automatiques. Ils facilitent la construction et la maintenance des interfaces - beaucoup.
  • Fermetures/lambdas . J'ai été vraiment déçu quand j'ai entendu que Java était repoussé encore.Enfin, nous avons des fermetures/lambdas dans Java 8, mais le temps qu'il a fallu atteste de ma déclaration sur l'adoption lente.
  • L'inférence de type (var) peut sembler syntaxique sucre, mais lorsque vous avez des types génériques complexes, cela peut rendre le code beaucoup plus clair en supprimant beaucoup de duplication inutile.
  • Les classes partielles aident vraiment à séparer le code généré automatiquement (par exemple à partir d'un générateur d'interface graphique) du code écrit par le programmeur.
  • Types de valeurs , il existe parfois un argument pour utiliser un poids léger struct sur une classe complète.
  • Les méthodes d'extension peuvent rendre les systèmes complexes si elles sont trop utilisées, mais sont idéales pour indiquer la manière canonique d'implémenter quelque chose pour une classe si c'est nécessaire.
  • Types non signés , parfois ce bit supplémentaire peut faire toute la différence. * 8 ')

Ce que je ne manque pas en Java, comparé à C #

  • La surcharge de l'opérateur est excellente lorsqu'elle est utilisée correctement, mais lorsqu'elle est mal utilisée, il peut en résulter des bogues difficiles à trouver et une déconnexion entre ce qu'un opérateur devrait évidemment faire et ce qu'il fait en fait fait.
  • Les types à valeur nulle semblaient toujours causer plus de problèmes qu'ils n'en valaient.
  • Accès au code unsafe. Vous devez être donc prudent avec cela que j'ai rarement trouvé que cela valait l'effort supplémentaire.

En tant que tel, même lorsque l'on compare des pommes à des pommes, Java est considéré comme ayant pris du retard.

Les deux autres gros problèmes que je vois avec Java sont le retard de démarrage flagrant et le fait que (pour certaines JVM) vous devez microgérer votre tas et même - tas de génération permanente . Avec les applications C # toujours démarrées immédiatement et je n'ai jamais eu à penser à un tas, car il était alloué hors du pool de mémoire système, pas à partir d'un pool pré-alloué affecté à la machine virtuelle .

11
Mark Booth

Je peux vous indiquer une source qui pourrait vous aider à répondre à la première partie de votre question. Les langages de programmation sortent http://shootout.alioth.debian.org/u64q/which-programming-languages-are-fastest.php est une très bonne source pour voir à quelle vitesse les langages se comparent les uns aux autres . Ils peuvent même être filtrés sur différentes catégories pour voir dans quels domaines les langues font mieux que d'autres. Java est beaucoup plus rapide qu'il y a plusieurs années.

8
bschaffer13

1) En parlant strictement de l'UX que je reçois avec Java, cela semble lent. Je ne peux pas vraiment vous dire pourquoi. Je n'ai pas encore rencontré de Java, qui ne se sent lente et a une alternative non Java plus rapide. Cela étant dit, Java peut être très rapide en vitesse de calcul pure et Internet regorge de références pour le prouver. Cependant, le temps de démarrage de Java apps et la réactivité de leurs interfaces graphiques n'a pas encore amélioré à mon humble avis. Peut-être pourriez-vous le faire;)
Au final, la vitesse n'est pas vraiment un problème. Non seulement le matériel devient de plus en plus rapide, mais aussi que la plupart des gens s'en soucient étonnamment peu tant que le logiciel le fait, ce qu'il doit faire et le rapport entre le temps passé à interagir et le temps passé à attendre est raisonnable.

2) Cette distinction est devenue si floue ces derniers temps, qu'elle a vraiment peu de valeur.

3 + 4) Il y a eu pas mal de changements à Java en fait. Certaines personnes soutiennent déjà, que ces changements ont entaché la philosophie purement simpliste de Java en renforçant les fonctionnalités extraterrestres. Il est vraiment difficile de dire objectivement, ce qu'est un défaut et ce qu'est une force. Pour moi, Java est inutilement verbeux, restrictif et pauvre en fonctionnalités, tandis que d'autres personnes considèrent ces traits mêmes comme une ambiguïté, une sécurité et une clarté agréables.
Alors même si ce sont ces choses qui me font personnellement ne pas utiliser Java, je ne pense pas simplement ajouter les choses qui me manquent dans Java est une bonne idée. Il y a beaucoup de j'aime courir sur la JVM et plier Java pour être plus proche d'eux irait à l'encontre du but de Java.

C'est une question de préférence

Le truc avec Java est qu'il est conçu pour vous empêcher de vous tirer une balle dans le pied. Une noble cause, mais avec toutes les restrictions qu'il vous attache, il n'est pas improbable que vous trébucher sur l'un de vos pieds sûrs, ne pouvez pas vous attacher avec vos mains attachées derrière votre dos pour votre propre sécurité et enfin mourir, parce que vous vous cassez le crâne.: D
D'une certaine manière, Java était une réponse à C++, qui vous donne assez de corde pour vous accrocher non seulement, mais aussi pour le reste du monde. C'est toute cette corde, qui le rend si attrayant pour les cowboys. Toute cette liberté et toute cette puissance.

Autrement dit, ce n'est vraiment qu'une question de préférence.

Mais, un point est que, avec C++ comme alternative à Java, vous êtes libre de choisir vos propres restrictions. Ou pour devenir vraiment fou avec tout le contrôle que vous avez, au risque de confondre complètement vos pairs:

J'ai vu "cout" être décalé des fois "Hello world" vers la gauche et je me suis arrêté là.
- Steve Gonedes

Java a choisi de ne pas proposer de surcharge d'opérateur, pour cette même raison. Bien sûr, cela empêche les gens d'obscurcir leur code en multipliant les pointeurs de fonction par des listes. Mais en même temps, cela empêche d'autres personnes d'effectuer des calculs géométriques/algébriques avec les opérateurs habituels. (v1 * v2 / scale) + (v3 * m) Est vraiment beaucoup plus clair que v1.multiply(v2).divide(scale).add(v3.multiply(m)). Je vois pourquoi cela peut rebuter les gens qui s'occupent des graphiques et des calculs 3D.

Java a choisi d'imposer le garbage collection, alors qu'en C++ vous pouvez choisir. Vous pouvez vraiment creuser complètement et vous rapprocher du matériel. Vous pouvez compresser les données de manière dense dans des structures. Vous pouvez effectuer de la magie noire, comme la racine carrée inverse rapide . Vous pouvez effectuer certaines des métaprogrammations les plus compliquées et les plus énigmatiques sur terre à l'aide de modèles. Mais cela signifie également que vous pouvez vous perdre et passer des heures à déboguer tous les dégâts que vous avez créés ou à rechercher des erreurs de compilation absolument inutiles.
Mais si vous avez la discipline de n'utiliser que les parties du langage que vous maîtrisez vraiment, vous pouvez écrire du code C++ aussi sûrement que Java code, mais vous avez la possibilité de poussant progressivement vers l'avant.

Donc, bien que rien ne vous empêche techniquement d'écrire des logiciels de pointe avec Java, vous constaterez que de nombreux développeurs sont vraiment passionnés par l'écriture de bons logiciels et par le plaisir et l'évolution tout en allant au-delà de ce que Java doit offrir comme langue.

Mais le monde ne se compose pas uniquement de personnes déterminées à créer la prochaine grande chose ou uniquement de personnes qui restreindront l'utilisation du pouvoir qui leur est donné uniquement dans la mesure où elles le contrôlent. À mon humble avis Java est le match parfait pour les personnes qui veulent produire des résultats stables d'une manière confortable.

4
back2dos

La collecte des ordures est la grande chose. De temps en temps, GC verrouille tout le reste pendant plusieurs centaines de millisecondes (selon la taille du tas) et effectue une collecte importante. C'est très bien si vous n'avez pas de contraintes de temps, mais si être en retard signifie un échec, c'est un arrêt de spectacle. Vous pouvez dépenser de l'argent pour Java en temps réel et un système d'exploitation en temps réel, mais vous pouvez simplement utiliser GCC et Linux standard et vous n'aurez pas ces problèmes.

Sans les pauses aléatoires imprévisibles, Java est probablement assez rapide pour la plupart des choses de nos jours. Et si vous passez des mois à modifier vos paramètres GC et ainsi de suite, peut-être, peut-être, vous pouvez le faire fonctionner longtemps assez pour que le client vous coupe un chèque.

0
Kevin