118 votes

Pourquoi la JVM ne met-elle pas en cache le code compilé par JIT ?

L'implémentation canonique de la JVM de Sun applique une optimisation assez sophistiquée au bytecode afin d'obtenir des vitesses d'exécution quasi-natives après que le code ait été exécuté plusieurs fois.

La question est de savoir pourquoi ce code compilé n'est pas mis en cache sur le disque pour être utilisé lors des utilisations ultérieures de la même fonction/classe.

Actuellement, chaque fois qu'un programme est exécuté, le compilateur JIT s'active à nouveau, au lieu d'utiliser une version précompilée du code. L'ajout de cette fonctionnalité ne permettrait-il pas d'augmenter considérablement le temps d'exécution initial du programme, lorsque le bytecode est essentiellement interprété ?

4 votes

Un fil de discussion sur ce problème : javalobby.org/forums/thread.jspa?threadID=15812

2 votes

Mais il est peu probable que cette question reçoive une réponse définitive.

1 votes

Je ne suis pas sûr qu'il s'agisse d'un coup de pouce "significatif", car il faudrait alors charger les éléments JIT depuis le disque au lieu de les JITer en mémoire. Cela pourrait accélérer les choses, mais au cas par cas.

32voto

Alex Martelli Points 330805

JVM d'Oracle est en effet documenté pour le faire -- citant Oracle,

le compilateur peut tirer parti du modèle de résolution de classe d'Oracle JVM pour pour faire persister les méthodes Java compilées compilées à travers les appels à la base de données, sessions ou instances. Une telle persistance persistance permet d'éviter les surcharges de recompilations inutiles entre les sessions ou instances, lorsque l'on sait que lorsque l'on sait que sémantiquement le code Java n'a pas changé.

Je ne sais pas pourquoi toutes les implémentations sophistiquées de VM ne proposent pas des options similaires.

8 votes

Parce que les autres JVM sophistiquées n'ont pas de SGBD d'entreprise à portée de main pour stocker des données :)

0 votes

Wow ! Cela signifie que les compilations sont parfois mises en cache. C'est une bonne nouvelle !

0 votes

Le J9 d'IBM est également documenté pour le faire.

32voto

skaffman Points 197885

Sans avoir recours à un copier-coller du lien que @MYYN a posté, je soupçonne que c'est parce que les optimisations que la JVM effectue ne sont pas statiques, mais plutôt dynamiques, basées sur les modèles de données ainsi que sur les modèles de code. Il est probable que ces modèles de données changent pendant la durée de vie de l'application, rendant les optimisations en cache moins qu'optimales.

Il faudrait donc un mécanisme permettant de déterminer si les optimisations sauvegardées sont toujours optimales, auquel cas il serait tout aussi bien de les réoptimiser à la volée.

7 votes

...ou vous pourriez simplement proposer la persistance comme une option comme le fait la JVM d'Oracle. programmeurs avancés d'optimiser les performances de leurs applications au moment et à l'endroit où ils le souhaitent. connaître les motifs sont pas changeant, sous leur responsabilité. Pourquoi pas ?

2 votes

Parce que ça n'en vaut probablement pas la peine. Si ni SUN, ni IBM, ni BEA n'ont considéré que cela valait la peine pour leurs JVM performantes, il doit y avoir une bonne raison pour cela. Peut-être que leur optimisation RT est plus rapide que celle d'Oracle, ce qui explique pourquoi Oracle la met en cache.

12 votes

Pourquoi ne pas prendre les optimisations stockées comme point de départ, pour utiliser ce qui a été appris lors des passages précédents ? A partir de là, le JIT pourrait fonctionner comme d'habitude et ré-optimiser les choses. À l'arrêt, ce code pourrait être à nouveau conservé et utilisé comme nouveau point de départ lors de la prochaine exécution.

19voto

Eugen Points 1444

Une mise à jour des réponses existantes - Java 8 a un JEP dédié à la résolution de ce problème :

\=> JEP 145 : Cache du code compilé . Nouveau lien .

À un niveau très élevé, il a déclaré L'objectif est :

Sauvegarder et réutiliser le code natif compilé des exécutions précédentes afin de améliorer le temps de démarrage des grandes applications Java.

J'espère que cela vous aidera.

4 votes

La fonction n'a pas été introduite dans le communiqué final .

0 votes

@assylias avec AOT il se peut que cela ne soit jamais nécessaire

8voto

Dmitry Leskov Points 1566

Excelsior JET possède un compilateur JIT de cache depuis la version 2.0, sortie en 2001. De plus, son compilateur AOT peut recompiler le cache en une seule DLL/objet partagé en utilisant toutes les optimisations.

4 votes

Oui, mais la question portait sur la JVM canonique, c'est-à-dire la JVM de Sun. Je suis bien conscient qu'il existe plusieurs compilateurs AOT pour Java ainsi que d'autres JVM à cache.

1voto

jk. Points 5780

Je ne connais pas les raisons réelles, n'étant pas impliqué de quelque manière que ce soit dans l'implémentation de la JVM, mais je peux penser à quelques raisons plausibles :

  • L'idée de Java est d'être un langage qui s'écrit une fois et s'exécute partout, et mettre du matériel précompilé dans le fichier de classe est en quelque sorte une violation de cela (seulement "en quelque sorte" parce que bien sûr le code d'octet réel serait toujours là).
  • Cela augmenterait la taille des fichiers de classe parce que vous auriez le même code plusieurs fois, surtout si vous exécutez le même programme sous plusieurs JVM différentes (ce qui n'est pas vraiment rare, si vous considérez les différentes versions comme des JVM différentes, ce que vous devez vraiment faire).
  • Les fichiers de classe eux-mêmes peuvent ne pas être accessibles en écriture (bien qu'il soit assez facile de le vérifier).
  • Les optimisations de la JVM sont partiellement basées sur des informations d'exécution et sur d'autres exécutions, elles pourraient ne pas être aussi applicables (bien qu'elles devraient toujours fournir un certain avantage).

Mais je suis vraiment en train de deviner, et comme vous pouvez le voir, je ne pense pas vraiment qu'aucune de mes raisons soit un obstacle réel. Je pense que Sun ne considère tout simplement pas ce support comme une priorité, et peut-être que ma première raison est proche de la vérité, car faire cela de manière habituelle pourrait aussi amener les gens à penser que les fichiers de classe Java ont vraiment besoin d'une version séparée pour chaque VM au lieu d'être multiplateforme.

Ma préférence irait en fait à un traducteur bytecode-natif distinct que vous pourriez utiliser pour faire quelque chose comme ça explicitement à l'avance, en créant des fichiers de classe qui sont explicitement construits pour une VM spécifique, avec éventuellement le bytecode d'origine en eux afin que vous puissiez fonctionner avec différentes VM aussi. Mais cela vient probablement de mon expérience : J'ai surtout travaillé sur Java ME, où le compilateur Java n'est pas plus intelligent pour la compilation.

1 votes

Il y a un endroit dans le fichier de classe pour de telles choses, en fait c'était l'intention originale (stocker le code JIT comme un attribut dans le fichier de classe).

0 votes

@TofuBeer : Merci pour la confirmation. Je me doutais que cela pouvait être le cas (c'est ce que j'aurais fait), mais je n'étais pas sûr. J'ai édité pour enlever cette raison possible.

0 votes

Je pense que vous avez mis le doigt sur le problème avec votre dernier point. Les autres peuvent être contournés, mais cette dernière partie est, je pense, la raison principale pour laquelle le code JIT n'est pas persistant.

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