java - ¿Por qué la JVM aún no es compatible con la optimización de la cola de llamadas?
language-agnostic optimization (4)
Dos años después does-the-jvm-prevent-tail-call-optimizations , parece haber una implementation prototype y MLVM ha incluido la característica como "proto 80%" desde hace algún tiempo.
¿No hay interés activo del lado de Sun / Oracle en apoyar las llamadas de cola o es solo que las llamadas de cola están "[...] predestinadas a ocupar el segundo lugar en cada lista de prioridades [...] de funciones" como se menciona en la JVM? Language Summit ?
Me interesaría mucho si alguien ha probado una versión de MLVM y podría compartir algunas impresiones de qué tan bien funciona (si es que lo hace).
Actualización: tenga en cuenta que algunas VM como Avian admiten llamadas de cola adecuadas sin ningún problema.
Java es el lenguaje menos funcional que puedas imaginar (bueno, vale, ¡ quizás no !) Pero esto sería una gran ventaja para los lenguajes de JVM, como Scala , que sí lo son.
Mis observaciones son que hacer que la JVM sea una plataforma para otros idiomas nunca pareció estar en la parte superior de la lista de prioridades para Sun y supongo, ahora para Oracle.
Quizás ya lo sepas, pero la función no es tan trivial como puede sonar, ya que el lenguaje Java realmente expone la traza de la pila al programador.
Considere el siguiente programa:
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());
}
}
Aunque esto tiene una "llamada final", puede que no se optimice. (Si está optimizado, todavía requiere la contabilidad de toda la pila de llamadas, ya que la semántica del programa se basa en ella).
Básicamente, esto significa que es difícil soportar esto sin dejar de ser compatible con versiones anteriores.
Una razón que he visto en el pasado para no implementar TCO (y que se ve como difícil) en Java es que el modelo de permiso en la JVM es sensible a la pila y, por lo tanto, las llamadas finales deben manejar los aspectos de seguridad.
Creo que esto no fue un obstáculo para Clements y Felleisen [1] [2] y estoy bastante seguro de que el parche MLVM mencionado en la pregunta también lo trata.
Me doy cuenta de que esto no responde a tu pregunta; solo agregando información interesante.
Diagnóstico de código Java: mejorar el rendimiento de su código Java ( alt ) explica por qué la JVM no es compatible con la optimización de la llamada final.
Pero aunque es bien sabido cómo transformar automáticamente una función recursiva de cola en un bucle simple, la especificación de Java no requiere que se realice esta transformación. Presumiblemente, una razón por la que no es un requisito es que, en general, la transformación no se puede realizar de forma estática en un lenguaje orientado a objetos. En cambio, la transformación de la función recursiva de la cola al bucle simple se debe hacer dinámicamente mediante un compilador JIT.
Luego da un ejemplo de código Java que no se transformará.
Entonces, como muestra el ejemplo en el Listado 3, no podemos esperar que los compiladores estáticos realicen la transformación de la recursividad de cola en el código de Java mientras preservan la semántica del lenguaje. En cambio, debemos confiar en la compilación dinámica del JIT. Dependiendo de la JVM, el JIT puede o no hacer esto.
Luego da una prueba que puede usar para determinar si su JIT hace esto.
Naturalmente, como se trata de un documento de IBM, incluye un complemento:
Ejecuté este programa con un par de SDK de Java, y los resultados fueron sorprendentes. Al ejecutar en el Hotspot de Sun, JVM para la versión 1.3 revela que el Hotspot no realiza la transformación. En la configuración predeterminada, el espacio de la pila se agota en menos de un segundo en mi máquina. Por otro lado, la JVM de IBM para la versión 1.3 ronronea sin problemas, lo que indica que sí transforma el código de esta manera.