2011-08-16 22 views
7

A working document que describe el estado de Project Lambda menciona los llamados tipos SAM (método abstracto único). Hasta donde sé, la propuesta actual de lambda no afecta el tiempo de ejecución solo al compilador al hacer posible la conversión automática de expresiones lambda a estos tipos.Java: optimización del tipo SAM

Creo que, en circunstancias ideales, las instancias de tipos de SAM podrían estar representadas internamente por indicadores de función. Por lo tanto, la JVM podría evitar la asignación de memoria para estas instancias.

Me pregunto si las máquinas virtuales modernas son capaces de proporcionar dicha optimización.

+0

Cuando dices "puntero a la función", ¿te refieres a un simple puntero al principio del código de la función? – ffriend

+0

@ffriend - Sí, lo hago.Sé que hay algunos problemas con este enfoque, por ejemplo, es posible sincronizar en un objeto. Pero la JVM también puede hacer otras optimizaciones no triviales, por ejemplo, en la creación de métodos virtuales. –

Respuesta

6

@ Tamás Usted probablemente debería tener una lectura de esta lista de correo mensaje por Brian Goetz:

http://mail.openjdk.java.net/pipermail/lambda-dev/2011-August/003877.html

Básicamente, la abstracción lambda se implementa actualmente el uso de objetos. Sin embargo, ha sido diseñado para permitir realizaciones alternativas de lambdas, que serían "más pequeñas" que las instancias de clases.

Puede pensar que la situación es similar a la del autoboxing - las entradas están encuadradas en Entero, pero tienen una representación "más pequeña" (como ints).

En la actualidad, las lambdas deben encasillarse en instancias de tipos de SAM, b/c la JVM actualmente no tiene manera de representar una lambda con una construcción más pequeña. En el futuro, puede haber un nuevo estándar JVM que incluye "funciones primitivas" que podrían representar lambdas como algo más que objetos.

Por lo tanto, para responder a su pregunta, puede ser posible el tipo de optimización que propone, pero probablemente vendrá después del trabajo posterior a Java 8 en "funciones primitivas" en lugar de ser una función específica de implementación.

5

No hay nada difícil en convertir clases de método único para los punteros a la función, pero le falta una cosa: las expresiones lambda no son solo funciones, son cierres. La diferencia es que los cierres pueden capturar variables externas. Considere siguiente ejemplo en seudo Java:

public Adder makeAdder(double startNumber) { 
    return #{ int number -> number + startNumber} 
} 

... 

int startNumber = 5; 
Adder add5 = makeAdder(startNumber); 
add5.invoke(4); // ==> 9 

En esta función ejemplo lambda, producido por la llamada a makeAdder(), se refiere a la variable que se define fuera de este lambda. Es por eso que se llama "cierres": están "cerrados" sus variables libres (en este caso, sobre el número de inicio). Para manejar tales situaciones, los cierres deben contener tanto el puntero a una función como el puntero a su entorno . Entonces, obtienes una estructura de datos que tiene un método y al menos una variable. Pero, ¿no es una definición de objeto en OOP? Entonces, ¿cuál es el motivo para crear nuevos tipos de objetos si puede convertirlos en una instancia de clase anónima?

Sin embargo, se pueden realizar algunas otras optimizaciones en clases anónimas. El documento de trabajo que usted mencionó menciona algunos de ellos, por ejemplo, inferir y usar efectivamente variables finales (aunque esto se hace principalmente para permitir el uso de lambdas en JVM en principio, no para optimizar el código). La clase anónima producida también puede finalizarse, y la mayoría de las JVM ya tienen buenas optimizaciones para los vars y las clases finales.

Otras mejoras también pueden referirse a las referencias al medio ambiente: hay muchas opciones allí.

+0

¡Gracias por la respuesta! Lo único que me preocupa es la asignación de memoria para estos objetos, lo que puede limitar la concurrencia, ya que, por lo que sé, cada asignación de memoria implica una cantidad de sincronizaciones. Por supuesto que sé que la gestión de objetos reutilizables es responsabilidad del programador, solo quería saber si la JVM puede evitar la asignación de memoria para estos objetos. –

+1

@ Tamás: ¿puede indicar los recursos sobre la sincronización durante la asignación de memoria? No puedo encontrar ninguna información sobre este tema, pero creo que la asignación de memoria predeterminada en JVM no usa cosas como 'synchronized': la asignación de un hilo en las VM modernas requiere solo una asignación a la referencia y un incremento de puntero. Creo que la seguridad de subprocesos en la asignación de memoria de subprocesos múltiples se realiza mediante algunas construcciones de muy bajo nivel, posiblemente basadas en operaciones atómicas del procesador, y por lo tanto también son muy rápidas. Si esto es así, no hay que preocuparse por la sincronización durante la creación del cierre. – ffriend

+3

@ Tamás Hotspot utiliza búferes TLS (almacenamiento local de subprocesos) internamente y solo si son asignaciones completas en el montón global, lo que puede ocasionar una sobrecarga de sincronización, pero de nuevo no es tan costoso, es solo un incremento de puntero en el caso normal (No lo sé, pero eso es casi seguro implementado con un bucle CAS). – Voo

Cuestiones relacionadas