gralvm grallvm java python jvm

java - grallvm - jython



¿Lengua de Java "máquina virtual" contra Python "intérprete"? (9)

Parece raro leer sobre una "máquina virtual" de Python, mientras que en Java se usa "máquina virtual" todo el tiempo.

Ambos interpretan códigos de bytes; ¿Por qué llamar a uno una máquina virtual y el otro a un intérprete?


El término intérprete es un término heredado que se remonta a los lenguajes de scripting de shell anteriores. Como los "lenguajes de scripting" han evolucionado hasta convertirse en lenguajes con todas las funciones y sus plataformas correspondientes se han vuelto más sofisticadas y aisladas, la distinción entre una máquina virtual y un intérprete (en el sentido de Python) es muy pequeña o inexistente.

El intérprete de Python todavía funciona de la misma manera que un script de shell, en el sentido de que se puede ejecutar sin un paso de compilación por separado. Más allá de eso, las diferencias entre el intérprete de Python (o Perl o Ruby) y la máquina virtual de Java son principalmente detalles de implementación. (Se podría argumentar que Java está más aislado que Python, pero ambos proporcionan acceso a la arquitectura subyacente a través de una interfaz C nativa).


En esta publicación, "máquina virtual" hace referencia a máquinas virtuales de proceso, no a máquinas virtuales de sistema como Qemu o Virtualbox. Una máquina virtual de proceso es simplemente un programa que proporciona un entorno de programación general, un programa que puede programarse.

Java tiene un intérprete y una máquina virtual, y Python tiene una máquina virtual además de un intérprete. La razón por la cual "máquina virtual" es un término más común en Java e "intérprete" es un término más común en Python tiene mucho que ver con la gran diferencia entre los dos idiomas: tipado estático (Java) vs tipado dinámico (Python). En este contexto, "tipo" se refiere a tipos de datos primitivos , tipos que sugieren el tamaño de almacenamiento en memoria de los datos. La máquina virtual Java lo tiene fácil. Requiere que el programador especifique el tipo de datos primitivo de cada variable. Esto proporciona información suficiente para que bytecode de Java no solo sea interpretado y ejecutado por la máquina virtual de Java, sino que incluso se compile en las instrucciones de la máquina . La máquina virtual de Python es más compleja en el sentido de que asume la tarea adicional de pausar antes de la ejecución de cada operación para determinar los tipos de datos primitivos para cada variable o estructura de datos involucrada en la operación. Python libera al programador de pensar en términos de tipos de datos primitivos, y permite que las operaciones se expresen en un nivel superior. El precio de esta libertad es el rendimiento. "Intérprete" es el término preferido para Python porque tiene que hacer una pausa para inspeccionar los tipos de datos, y también porque la sintaxis comparativamente concisa de los lenguajes de tipo dinámico es una buena opción para las interfaces interactivas. No existe una barrera técnica para construir una interfaz Java interactiva, pero tratar de escribir cualquier código estáticamente de forma interactiva sería tedioso, por lo que simplemente no se hace de esa manera.

En el mundo de Java, la máquina virtual roba el programa porque ejecuta programas escritos en un lenguaje que realmente se puede compilar en instrucciones de la máquina, y el resultado es la velocidad y la eficiencia de los recursos. Java bytecode puede ser ejecutado por la máquina virtual Java con un rendimiento similar al de los programas compilados, en términos relativos. Esto se debe a la presencia de información de tipo de datos primitivos en bytecode. La máquina virtual Java pone a Java en una categoría propia:

lenguaje portátil interpretado de tipo estático

La siguiente cosa más cercana es LLVM, pero LLVM opera en un nivel diferente:

lenguaje de ensamblado portátil interpretado

El término "bytecode" se usa tanto en Java como en Python, pero no todos los bytecode se crean iguales. bytecode es simplemente el término genérico para los lenguajes intermedios utilizados por los compiladores / intérpretes. Incluso los compiladores C como gcc utilizan un lenguaje intermedio (o varios) para realizar el trabajo. El bytecode de Java contiene información sobre tipos de datos primitivos, mientras que el bytecode de Python no. En este sentido, la máquina virtual Python (y Bash, Perl, Ruby, etc.) es fundamentalmente más lenta que la máquina virtual Java, o más bien, simplemente tiene más trabajo por hacer. Es útil considerar qué información está contenida en diferentes formatos de bytecode:

  • llvm: registros de la CPU
  • Java: tipos de datos primitivos
  • Python: tipos definidos por el usuario

Para dibujar una analogía del mundo real: LLVM trabaja con átomos, la máquina virtual Java trabaja con moléculas y la máquina virtual Python trabaja con materiales. Dado que todo debe descomponerse finalmente en partículas subatómicas (operaciones de máquinas reales), la máquina virtual Python tiene la tarea más compleja.

Los intérpretes / compiladores de lenguajes de tipo estático simplemente no tienen el mismo bagaje que tienen los intérpretes / compiladores de lenguajes de tipado dinámico. Los programadores de lenguajes tipados de forma estática tienen que tomar el relevo, para lo cual el pago es el rendimiento. Sin embargo, del mismo modo que todas las funciones no deterministas son secretamente deterministas, también lo son todos los lenguajes de tipo dinámico secretamente de tipo estático. Las diferencias de rendimiento entre las dos familias de idiomas deberían, por lo tanto, nivelarse alrededor del tiempo en que Python cambia su nombre a HAL 9000.

Las máquinas virtuales de lenguajes dinámicos como Python implementan una máquina lógica idealizada, y no necesariamente se corresponden muy estrechamente con ningún hardware físico real. La máquina virtual Java, por el contrario, es más similar en funcionalidad a un compilador clásico de C, excepto que en lugar de emitir instrucciones de máquina, ejecuta rutinas incorporadas. En Python, un entero es un objeto de Python con un conjunto de atributos y métodos asociados. En Java, un int es un número designado de bits, generalmente 32. En realidad no es una comparación justa. Los enteros de Python realmente deberían compararse con la clase Java Integer. El tipo de datos primitivo "int" de Java no se puede comparar con nada en el lenguaje Python, porque el lenguaje Python simplemente carece de esta capa de primitivos, al igual que el código de bytes de Python.

Debido a que las variables Java están explícitamente tipadas, se puede esperar razonablemente que algo como el rendimiento de Jython esté en el mismo estadio que cPython . Por otro lado, es casi seguro que una máquina virtual Java implementada en Python sea más lenta que el lodo. Y no esperes que Ruby, Perl, etc., vayan mejor. No fueron diseñados para hacer eso. Fueron diseñados para "secuencias de comandos", que es lo que se llama programación en un lenguaje dinámico.

Cada operación que tiene lugar en una máquina virtual finalmente tiene que llegar al hardware real. Las máquinas virtuales contienen rutinas pre compiladas que son lo suficientemente generales como para ejecutar cualquier combinación de operaciones lógicas. Una máquina virtual puede no emitir nuevas instrucciones de máquina, pero sin duda está ejecutando sus propias rutinas una y otra vez en secuencias complejas. La máquina virtual Java, la máquina virtual Python y todas las otras máquinas virtuales de uso general que existen son iguales en el sentido de que se las puede convencer para que realicen cualquier lógica que se les ocurra, pero son diferentes en términos de las tareas que asumir, y qué tareas le dejan al programador.

Psyco para Python no es una máquina virtual completa de Python, sino un compilador justo a tiempo que secuestra la máquina virtual de Python en puntos que cree que puede compilar unas pocas líneas de código, principalmente bucles donde cree que es el tipo primitivo de algunos la variable permanecerá constante incluso si el valor cambia con cada iteración. En ese caso, puede renunciar a parte de la determinación de tipo incessent de la máquina virtual normal. Sin embargo, debes tener un poco de cuidado, para que no saques el tipo de debajo de los pies de Psyco. Sin embargo, Pysco generalmente sabe que simplemente recurre a la máquina virtual normal si no está completamente seguro de que el tipo no cambiará.

La moraleja de la historia es que la información del tipo de datos primitivos es realmente útil para un compilador / máquina virtual.

Finalmente, para poner todo en perspectiva, considere esto: un programa de Python ejecutado por un intérprete / máquina virtual de Python implementado en Java que se ejecuta en un intérprete / máquina virtual Java implementado en LLVM que se ejecuta en una máquina virtual qemu que se ejecuta en un iPhone.

permalink


En primer lugar, debe comprender que la programación o la informática en general no son matemáticas y no tenemos definiciones rigurosas para la mayoría de los términos que usamos a menudo.

ahora a tu pregunta:

qué es un intérprete (en informática)

Traduce el código fuente por la unidad ejecutable más pequeña y luego ejecuta esa unidad.

que es una maquina virtual

en el caso de JVM, la máquina virtual es un software que contiene un intérprete, cargadores de clases, recolector de basura, programador de hilos, compilador JIT y muchas otras cosas.

como puede ver, el intérprete es una parte o JVM y JVM no puede llamarse intérprete porque contiene muchos otros componentes.

¿Por qué usar la palabra "Intérprete" cuando se habla de pitón?

con Java, la parte de compilación es explícita. Python, por otro lado, no es explícita como java sobre su proceso de compilación e interpretación, desde la perspectiva de la interpretación del usuario final es el único mecanismo utilizado para ejecutar programas de Python.


No hay diferencia real entre ellos, la gente simplemente sigue las convenciones que los creadores han elegido.


No olvide que Python tiene compiladores JIT disponibles para x86, lo que confunde aún más el problema. (Ver psyco).

Una interpretación más estricta de un "lenguaje interpretado" solo se vuelve útil cuando se discuten los problemas de rendimiento de la VM, por ejemplo, en comparación con Python, Ruby fue (¿es?) Considerado más lento porque es un lenguaje interpretado, a diferencia de Python - en otra palabras, el contexto es todo.


No, ambos no interpretan el código de bytes.

Python solo interpreta bytecode si está ejecutando con pypy. De lo contrario, se compila en C e interpreta en ese nivel.

Java compila a bytecode.


Probablemente una de las razones de la terminología diferente es que normalmente se piensa en alimentar el código fuente bruto interpretable por el intérprete de Python sin preocuparse por bytecode y todo eso.

En Java, tiene que compilar explícitamente a bytecode y luego ejecutar solo el bytecode, no el código fuente en la VM.

A pesar de que Python usa una máquina virtual bajo las sábanas, desde la perspectiva de un usuario, uno puede ignorar este detalle la mayor parte del tiempo.


Una máquina virtual es un entorno informático virtual con un conjunto específico de instrucciones atómicas bien definidas que se admiten independientemente de cualquier lenguaje específico y, en general, se considera una caja de arena en sí misma. La VM es análoga a un conjunto de instrucciones de una CPU específica y tiende a funcionar en un nivel más fundamental con bloques de construcción muy básicos de tales instrucciones (o códigos de bytes) que son independientes de la siguiente. Una instrucción se ejecuta de forma determinista solo en el estado actual de la máquina virtual y no depende de la información en ningún otro lugar de la secuencia de instrucciones en ese momento.

Por otro lado, un intérprete es más sofisticado ya que está diseñado para analizar una secuencia de alguna sintaxis que es de un lenguaje específico y de una gramática específica que debe decodificarse en el contexto de los tokens circundantes. No puede ver cada byte o incluso cada línea aisladamente y saber exactamente qué hacer a continuación. Los tokens en el idioma no se pueden tomar de forma aislada como lo hacen en relación con las instrucciones (códigos de bytes) de una máquina virtual.

Un compilador de Java convierte el lenguaje Java en una secuencia de código de bytes no diferente de un compilador de C convierte programas de lenguaje C en código de ensamblaje. Por otro lado, un intérprete realmente no convierte el programa en una forma intermedia bien definida, simplemente toma las acciones del programa como una cuestión del proceso de interpretación de la fuente.

Otra prueba de la diferencia entre una VM y un intérprete es si lo considera independiente del lenguaje. Lo que conocemos como Java VM no es realmente específico de Java. Puede crear un compilador de otros idiomas que resulte en códigos de bytes que se pueden ejecutar en la JVM. Por otro lado, no creo que realmente pensáramos en "compilar" algún otro idioma que no sea Python en Python para la interpretación del intérprete de Python.

Debido a la sofisticación del proceso de interpretación, este puede ser un proceso relativamente lento ... específicamente analizar e identificar los tokens de idioma, etc. y comprender el contexto de la fuente para poder llevar a cabo el proceso de ejecución dentro del intérprete. Para ayudar a acelerar dichos lenguajes interpretados, aquí es donde podemos definir formas intermedias de código fuente pre-analizado, pre-tokenizado, que se interpretan más fácilmente. Este tipo de forma binaria todavía se interpreta en el momento de la ejecución, apenas está comenzando desde una forma mucho menos legible para mejorar el rendimiento. Sin embargo, la lógica que ejecuta esa forma no es una máquina virtual, porque esos códigos aún no se pueden tomar de forma aislada; el contexto de los tokens circundantes sigue siendo importante, ahora están en una forma diferente más eficiente en cuanto a la computadora.


Intérprete , traduce el código fuente en alguna representación intermedia eficiente (código) y lo ejecuta de inmediato.

Virtual Machine , ejecuta explícitamente código precompilado almacenado creado por un compilador que es parte del sistema de intérprete.

Una característica muy importante de una máquina virtual es que el software que se ejecuta dentro está limitado a los recursos proporcionados por la máquina virtual. Precisamente, no puede salir de su mundo virtual. Piense en la ejecución segura de código remoto, Applets de Java.

En el caso de Python, si guardamos archivos pyc , como se menciona en el comentario de esta publicación, entonces el mecanismo se parecería más a una máquina virtual, y este bytecode se ejecutaría más rápido: aún sería interpretado, pero desde una forma mucho más amigable para la computadora . Si miramos esto como un todo, PVM es el último paso del intérprete de Python.

La conclusión es que, cuando se refiere a Python Interpreter, significa que lo estamos refiriendo como un todo, y cuando decimos PVM, eso significa que estamos hablando de una parte de Python Interpreter, un entorno de ejecución. Similar a la de Java, nos referimos a diferentes partes differentyl, JRE, JVM, JDK, etc.

Para más información, entrada de Wikipedia: Interpreter y máquina virtual . Otra más here . Aquí puede encontrar la Comparación de máquinas virtuales de aplicaciones . Ayuda a comprender la diferencia entre compiladores, intérpretes y máquinas virtuales.