54 votes

Pourquoi Java est plus rapide lors de l'utilisation d'un JIT vs compilation en code machine?

J'ai entendu dire que Java doit utiliser un JIT pour être rapide. Cela prend tout son sens lorsque l'on compare à l'interprétation, mais pourquoi ne peut-on faire une avance compilateur qui génère rapide de code Java? Je sais à propos de gcj, mais je ne pense pas que sa sortie est généralement plus rapide que Hotspot par exemple.

Existe-il des choses à propos de la langue qui font de ce difficile? Je crois qu'au fond de ces choses:

  • La réflexion
  • Classloading

Ce qui me manque? Si je éviter ces fonctionnalités, serait-il possible de compiler du code Java une fois le code machine natif, et doit être fait?

45voto

Andrew Hare Points 159332

Un compilateur JIT peut être plus rapide parce que le code machine est généré sur la même machine que l'on s'exécuter. Cela signifie que l'équipe a la meilleure information disponible pour émettre un code optimisé.

Si vous pré-compile le bytecode en code machine, le compilateur ne peut pas optimiser pour la machine cible(s), seulement la machine de compilation.

34voto

Edwin Dalorzo Points 19899

Je vais coller une réponse intéressante donnée par James Gosling lui-même dans le Livre des Penseurs de la Programmation.

Eh bien, j'ai entendu dire que effectivement, vous avez deux compilateurs dans le monde Java. Vous avez le compilateur pour le bytecode Java, et puis vous avez votre JIT, qui, fondamentalement, recompile tout spécialement à nouveau. Tous votre effrayant optimisations sont dans le JIT.

James: Exactement. Ces jours que nous sommes battre le très bon le C et le C++ les compilateurs d'à peu près toujours. Lorsque vous aller à la dynamique du compilateur, vous obtenez deux avantages lorsque le compilateur à droite au dernier moment. Un est que vous savez exactement ce chipset vous êtes en cours d'exécution sur. Bien souvent, quand les gens sont à la compilation d'un morceau de C code, ils doivent compiler pour qu'il fonctionne sur la nature du générique x86 de l'architecture. Presque aucun des les binaires que vous obtenez sont particulièrement bien à l'écoute de l'un d'eux. Vous téléchargez la dernière version de Mozilla,et il va exécuter sur quasiment tous les processeurs Intel l'architecture du PROCESSEUR. Il est assez bien un binaire Linux. C'est assez générique, et il est compilé avec GCC, qui est pas un très bon compilateur C.

Lorsque HotSpot fonctionne, il sait exactement ce chipset vous êtes en cours d'exécution sur. Il sait exactement comment le cache fonctionne. Il sait exactement comment la hiérarchie de mémoire des œuvres. Il sait exactement comment tous les pipeline de dispositifs de verrouillage de travail de la CPU. Il sait que le jeu d'instructions des extensions de cette puce a eu. Il optimise pour précisément ce que la machine vous êtes sur. Ensuite l'autre moitié de lui c'est qu'il voit réellement le l'application est en cours d'exécution. Il est capable pour avoir des statistiques qui sais qui choses sont importantes. Il est capable de inline choses qu'un compilateur C pourrait ne jamais faire. Le genre de truc qui se inline dans le monde Java est assez incroyable. Ensuite, vous tack sur que le façon de la gestion du stockage fonctionne avec le moderne ramasseurs d'ordures. Avec un moderne garbage collector, de stockage l'allocation est extrêmement rapide.

Masterminds of Programming

24voto

Le véritable assassin pour toute AOT compilateur est:

Class.forName(...)

Cela signifie que vous ne pouvez pas écrire un AOT compilateur qui couvre TOUS les programmes Java comme il y a de l'information disponible uniquement lors de l'exécution sur les caractéristiques du programme. Vous pouvez, cependant, faire sur un sous-ensemble de Java, qui est ce que je crois que gcj n'.

Un autre exemple typique est la capacité d'une équipe commune d'enquête d'inline méthodes comme getX() directement dans les méthodes d'appel s'il est constaté qu'il est sécuritaire de le faire et défaire le cas échéant, même si pas explicitement aidé par le programmeur en disant qu'une méthode est définitive. Le JIT peut le voir dans le programme en cours d'exécution d'une méthode donnée n'est pas surchargée et est, par conséquent, dans la présente instance peut être considérée comme définitive. Cela peut être différent dans la prochaine invocation.

23voto

Luke Quinane Points 8257

Java compilateur JIT est aussi paresseux et adaptative.

Paresseux

Être paresseux, il ne compile méthodes quand il arrive à la place de la compilation de l'ensemble du programme (très utile si vous n'utilisez pas partie d'un programme). Chargement de classe permet effectivement de rendre l'équipe plus rapide, en permettant d'ignorer les classes, il n'a pas trouver encore.

Adaptative

Être adaptable, elle émet un rapide et sale de la version de la machine code abord, puis seulement va à l'arrière et fait un travail si cette méthode est fréquemment utilisée.

12voto

Tal Pressman Points 4120

En fin de compte, il se résume au fait que le fait d'avoir plus d'informations permet une meilleure optimisation. Dans ce cas, l'équipe a plus d'informations sur la machine réelle, le code est en cours d'exécution sur (comme Andrew dessus) et elle a aussi beaucoup d'informations d'exécution qui n'est pas disponible lors de la compilation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X