web-dev-qa-db-fra.com

Pourquoi la JVM ne prend-elle toujours pas en charge l'optimisation des appels de queue?

Deux ans après optimise-jvm-prevent-tail-call-optimisations , il semble y avoir prototypeimplémentation et MLVM a répertorié la fonctionnalité comme "proto 80%" depuis un certain temps maintenant.

N'y a-t-il aucun intérêt actif de la part de Sun/Oracle à prendre en charge les appels de queue ou est-ce juste que les appels de queue sont "[...] destinés à venir en deuxième position sur chaque liste de priorité des fonctionnalités [. ..] "comme mentionné lors du JVM Language Summit ?

Je serais vraiment intéressé si quelqu'un a testé une build MLVM et pourrait partager quelques impressions sur son bon fonctionnement (le cas échéant).

Mise à jour: Notez que certaines machines virtuelles comme Avian prennent en charge la queue appropriée- appels sans aucun problème.

95
soc

Diagnostic Java: Amélioration des performances de votre Java) ( alt ) explique pourquoi la JVM ne prend pas en charge l'optimisation des appels de queue.

Mais bien qu'il soit bien connu de transformer automatiquement une fonction récursive de queue en une boucle simple, la spécification Java n'exige pas que cette transformation soit effectuée. Vraisemblablement, une raison pour laquelle ce n'est pas un l'exigence est que, en général, la transformation ne peut pas être effectuée de manière statique dans un langage orienté objet. Au lieu de cela, la transformation de la fonction récursive de queue en boucle simple doit être effectuée dynamiquement par un compilateur JIT.

Il donne ensuite un exemple de Java qui ne se transforme pas.

Ainsi, comme le montre l'exemple du Listing 3, nous ne pouvons pas nous attendre à ce que les compilateurs statiques effectuent la transformation de la récursivité de queue sur Java tout en préservant la sémantique du langage. Au lieu de cela, nous devons compter sur une compilation dynamique par Selon le JVM, le JIT peut ou non faire cela.

Ensuite, il donne un test que vous pouvez utiliser pour déterminer si votre JIT le fait.

Naturellement, puisqu'il s'agit d'un document IBM, il comprend une prise:

J'ai exécuté ce programme avec quelques-uns des kits de développement Java SDK, et les résultats ont été surprenants. L'exécution sur la machine virtuelle Java Hotspot de Sun pour la version 1.3 révèle que Hotspot n'effectue pas la transformation. l'espace de pile est épuisé en moins d'une seconde sur ma machine. D'autre part, la JVM d'IBM pour la version 1.3 ronronne sans problème, indiquant qu'elle transforme le code de cette façon.

32
emory

Une raison que j'ai vue dans le passé pour ne pas implémenter TCO (et cela est considéré comme difficile) dans Java est que le modèle d'autorisation dans la JVM est sensible à la pile et donc les appels de queue doivent gérer les aspects de sécurité.

Je pense que Clements et Felleisen [1] [2] ont montré que cela ne constituait pas un obstacle et je suis pratiquement sûr que le correctif MLVM mentionné dans la question le traite également.

Je me rends compte que cela ne répond pas à votre question; juste ajouter des informations intéressantes.

  1. http://www.ccs.neu.edu/scheme/pubs/esop2003-cf.pdf
  2. http://www.ccs.neu.edu/scheme/pubs/cf-toplas04.pdf
30
Alex Miller

Peut-être le savez-vous déjà, mais la fonctionnalité n'est pas aussi triviale que cela puisse paraître car le langage Java expose en fait la trace de la pile au programmeur.

Considérez le programme suivant:

public class Test {

    public static String f() {
        String s = Math.random() > .5 ? f() : g();
        return s;
    }

    public static String g() {
        if (Math.random() > .9) {
            StackTraceElement[] ste = new Throwable().getStackTrace();
            return ste[ste.length / 2].getMethodName();
        }
        return f();
    }

    public static void main(String[] args) {
        System.out.println(f());
    }
}

Même si cela a un "appel de queue", il peut ne pas être optimisé. (Si elle est optimisée, elle nécessite toujours la tenue de livres de la pile d'appels entière puisque la sémantique du programme en dépend.)

Fondamentalement, cela signifie qu'il est difficile de prendre en charge cela tout en étant rétrocompatible.

14
aioobe

Java est le langage le moins fonctionnel que vous puissiez imaginer (enfin, OK, peut-être pas !) Mais ce serait un grand avantage pour les langages JVM, comme Scala , qui le sont.

Mes observations sont que faire de la JVM une plate-forme pour d'autres langues n'a jamais semblé être en tête de liste des priorités pour Sun et je suppose, maintenant pour Oracle.

12
oxbow_lakes