¿Por qué los lenguajes VM no se compilan solo una vez?

8

(En primer lugar, debo dejar en claro que los compiladores y las máquinas virtuales ( aka ) son un campo completamente desconocido para mí)

Según tengo entendido, cada vez que se ejecuta una aplicación Java / C # / ..., se invoca una VM y traduce el código intermedio (bytecode, CIL, etc.) a las instrucciones de la máquina.

Pero, ¿por qué esta operación no puede hacerse solo una vez, en el momento de la instalación?

vemv
fuente
1
¿Qué es el tiempo de instalación?
Peter Taylor
3
No estoy seguro de si es un término estándar, pero quise decir: cuando el usuario instala el programa, lo ejecuta por primera vez, en lugar de compilar un programa en la máquina del desarrollador (que no puede conocer la plataforma que usará un usuario determinado) - y no desea distribuir un instalador por plataforma).
vemv
@vemv compilar en tiempo de ejecución le permite a la VM especializar las instrucciones de la máquina para su hardware en particular
Lucina

Respuestas:

8

En el caso de Java, la JVM puede hacer optimizaciones que cruzan los límites de la biblioteca. Por ejemplo, podría incluir un método de una biblioteca en su propio código de cliente. Este tipo de optimización no se pudo realizar en tiempo de compilación, porque la biblioteca puede cambiar antes de la ejecución. Es completamente posible que su libfoo-1.0 sea reemplazado por libfoo-1.1 sin una nueva compilación. Si eso sucede, las inline de bibliotecas cruzadas realizadas en tiempo de compilación serían totalmente inválidas.

Al hacer la optimización únicamente en tiempo de ejecución, no hay que preocuparse de que la biblioteca que cambie debajo de usted invalide las optimizaciones.

Steven Schlansker
fuente
1
Una línea podría ser en lugar de generar código de máquina para llamar a "Y.setX (x)" (donde Y es de una biblioteca de una tercera parte) que luego ejecuta "this.x = x" y luego solo genera código de máquina para "Yx = x ".
En resumen, el tiempo de ejecución tiene información que el tiempo de compilación no tiene.
Daniel Gratzer el
6

Porque esto les impide usar muchas funciones. Por ejemplo, ¿cómo puede el JIT generar nuevas instancias genéricas de las DLL cargadas en tiempo de ejecución? Esas DLL no existen en el momento de la instalación.

DeadMG
fuente
1
Saludos por la respuesta. Creo que tengo el problema de la instauración, aunque no puedo estar 100% seguro porque tu respuesta es demasiado sucinta. Además, enumerar otras características no disponibles fortalecería su punto.
vemv
3
O en general: un JIT puede hacer optimizaciones basadas en la entrada; Las DLL cargadas en tiempo de ejecución son un tipo de entrada.
amara
1
Obviamente, aquellos de DLL se instalan también, y cada DLL podrían ser compilados en su momento de la instalación. Pierdes optimizaciones entre módulos, pero de todos modos son un poco teóricas.
MSalters
@MSalters: no todas las DLL tienen un tiempo de "instalación".
DeadMG
@DeadMG: Estamos hablando de sistemas hipotéticos de todos modos; dicho sistema puede requerir fácilmente la instalación. (Sería un beneficio de seguridad, además, si la introducción de código ejecutable se gestionara explícitamente).
MSalters
5

Puede, y a menudo lo es, al menos con aplicaciones .NET. Ver generador de imágenes nativas

Una herramienta que mejora el rendimiento de las aplicaciones administradas. Ngen.exe crea imágenes nativas, que son archivos que contienen código de máquina específico del procesador compilado, y las instala en la memoria caché de imágenes nativas en la computadora local. El tiempo de ejecución puede usar imágenes nativas del caché en lugar de usar el compilador JIT (Just-In-Time) para compilar el ensamblaje original ...

Nemanja Trifunovic
fuente
Tenga en cuenta que esto también es similar al tiempo de ejecución de Android (ART) construido por Google para mejorar el rendimiento de aplicaciones Android
neelsg
3

Para reformular la pregunta de acuerdo con la aclaración:

¿Por qué no se puede compilar el código de bytes en código nativo la primera vez que se ejecuta el programa?

Veo los siguientes problemas:

  • ¿Dónde se almacenarían los resultados? No puede suponer que el archivo que contiene el bytecode se puede escribir; no desea inflar la máquina de un desarrollador volcando un nuevo .exe al almacenamiento permanente cada vez que ejecuta una prueba; y si almacena el archivo en un almacenamiento temporal, se perderá la próxima vez que reinicie, por lo que no ha ganado mucho.

  • Estás intercambiando un inicio un poco lento cada vez por un inicio muy lento la primera vez. No va a dejar una gran impresión con el cliente.

  • Tendrás problemas importantes con la carga dinámica de clases.

Peter Taylor
fuente
2
El primer punto es trivial. Los cachés se entienden bastante bien. Cuando se elimina el bytecode ejecutable subyacente, puede eliminar la entrada de caché asociada, y también si no se ejecuta durante demasiado tiempo. En cuanto al segundo punto, puede hacer la compilación de métodos no utilizados en un hilo de fondo. Esto no debería obstaculizar el tiempo de inicio, donde compila métodos llamados en primer plano.
MSalters
Según tengo entendido, la pregunta no es compilar en la primera ejecución, sino compilar en la instalación.
Nemanja Trifunovic
@NemanjaTrifunovic, lea los comentarios sobre la pregunta.
Peter Taylor
1
Me temo que no me expliqué bien, lo siento. Me refiero a la primera vez que una aplicación está siempre funciona, entonces se necesitarían más No hay más compilaciones. Al igual que cuando tienes que compilar un programa en C antes de usarlo en Linux.
vemv
1
Creo que prácticamente cuenta como una instalación: esas compilaciones / procesos de compilación ya están programados para usted.
vemv