2011-12-30 17 views
7

El código compilado como C consume poca memoria.¿Por qué el código JIT consume tanta memoria que el código compilado o interpretado?

El código interpretado como Python consume más memoria, lo cual es comprensible.

Con JIT, un programa se compila (selectivamente) en código de máquina en tiempo de ejecución. Entonces, ¿no debería el consumo de memoria de un programa JIT estar en algún lugar entre el de un programa compilado y el interpretado?

En cambio, un programa JIT (como PyPy) consume varias veces más memoria que el programa equivalente interpretado (como Python). ¿Por qué?

+0

Todo el mundo habla de que el JIT es la causa del aumento en el uso de memoria en Pypy, pero esa no es la historia completa. Si bien algunas de las estructuras de memoria de Pypy son más compactas (listas de todas las entradas, por ejemplo), Pypy tiene una variedad de recolectores de basura que se pueden usar con ella y definitivamente afectarán la cantidad de memoria en uso. El recolector de basura predeterminado actual en Pypy no hace recuento de referencias por razones de velocidad. Debido a esto, los objetos pueden permanecer en la memoria más tiempo de lo que lo harían en CPython y, por lo tanto, los programas pueden tener una mayor huella de memoria en Pypy. –

Respuesta

8

Los compiladores de rastreo JIT toman bastante más memoria debido al hecho de que necesitan mantener no solo el bytecode para la VM, sino también el código de máquina directamente ejecutable. esto es solo la mitad de la historia sin embargo.

La mayoría de los JIT también conservan una gran cantidad de metadatos sobre el bytecode (e incluso el código de máquina) para permitirles determinar qué necesita JIT y qué puede dejarse en paz. Los JIT de rastreo (como LuaJIT) también crean instantáneas de rastreo que se usan para ajustar el código en el tiempo de ejecución, realizando cosas como desenrollar bucles o reordenar ramas.

Algunos también mantener depósitos de segmentos de código de uso común o tampones de búsqueda rápida para acelerar la creación del código JIT'ed (LuaJIT hace a través de DynAsm, sino que puede ayudar a reducir el uso de memoria cuando se hace correctamente, como es el caso de dynasm)

El uso de la memoria depende en gran medida del motor JIT empleado y la naturaleza del lenguaje que compila (fuertemente contra débilmente tipado). algunos JIT emplean técnicas avanzadas tales como asignadores de registro basados ​​en SSA y análisis de animación variable, este tipo de optimizaciones también ayudan a consumir memoria, junto con las cosas más comunes, como la elevación variable de bucle.

+1

Además, JIT es una compilación en tiempo real, por lo que debe sacrificar la optimización por la velocidad. Un compilador fuera de línea puede permitirse pasar 5 segundos optimizando una función. Un JIT no tanto. –

+0

@RaymondChen: depende totalmente del JIT, si está escrito correctamente, no es necesario sacrificar * esa * gran optimización, solo son realmente las costosas técnicas de análisis que se han perdido. – Necrolis

+0

Además, los JIT generalmente son * compiladores * especializados. El objetivo de hacer compilación "justo a tiempo" es que el compilador pueda esperar y ver qué se está utilizando en el tiempo de ejecución y optimizarlo específicamente para eso. Lo que significa (dependiendo del JIT) que puede haber varias versiones diferentes del código de máquina para una sección determinada de bytecode en la memoria en cualquier momento, junto con el código de bytes original en caso de que surja una nueva situación que no encaje cualquiera de las versiones compiladas – Ben

5

Tenga cuidado con lo que tipo de memoria está hablando.

El código compilado para C utiliza comparativamente poca memoria para el código de máquina compilada en sí.

Esperaría que el bytecode de Python para un algoritmo determinado fuera realmente más pequeño que el código C compilado para un algoritmo similar, porque las operaciones de bytecode de Python son de un nivel mucho mayor, por lo que a menudo hay menos de ellas para hacer algo. Pero un programa de Python también tendrá el código compilado del intérprete de Python en la memoria, que es un programa bastante grande y complejo en sí mismo. Además, un programa típico de Python tendrá mucha más biblioteca estándar en la memoria que un programa típico de C (y un programa de C puede eliminar todas las funciones que en realidad no usa si está vinculado estáticamente, y si está vinculado dinámicamente, entonces comparte el código compilado con cualquier otro proceso en memoria que lo use).

PyPy tiene encima de esto el código de máquina del compilador JIT, así como el código de máquina generado a partir del bytecode de Python (que no desaparece, debe mantenerse también). Por lo tanto, su intuición (que un sistema JITed "debería" consumir memoria en algún lugar entre la de un lenguaje compilado y un lenguaje totalmente interpretado) no es correcta de todos modos.

Pero además de todo eso, usted tiene la memoria real utilizada por las estructuras de datos en las que opera el programa. Esto varía enormemente, y tiene poco que ver con si el programa se compila antes de tiempo, o se interpreta, o se interpreta y se JIT.Algunas optimizaciones del compilador reducirán el uso de la memoria (ya sea que se apliquen con anticipación o justo a tiempo), pero en realidad muchos intercambian el uso de la memoria para ganar velocidad. Para los programas que manipulan cualquier cantidad seria de datos, empequeñecerá por completo la memoria utilizada por el código en sí, de todos modos.

Cuando dicen:

En lugar de un programa JIT'ed (como PyPy) consumen varias veces más memoria que el programa interpretado equivalente (como Python). ¿Por qué?

¿En qué programas estás pensando? Si has hecho alguna comparación, supongo que por tu pregunta estarían entre PyPy y CPython. Sé que muchas de las estructuras de datos de PyPy son en realidad más pequeñas que las de CPython, pero una vez más, eso no tiene nada que ver con el JIT.

Si el uso dominante de memoria de un programa es el código en sí, un compilador JIT agrega gran sobrecarga de memoria (para el compilador y el código compilado) y no puede hacer mucho para "recuperar "uso de memoria a través de la optimización. Si el uso dominante de la memoria son las estructuras de datos del programa, entonces no me sorprendería en absoluto que PyPy use mucha menos memoria que CPython, esté o no habilitado el JIT.


No hay realmente una respuesta directa a su "¿Por qué?" porque las declaraciones en su pregunta no son directamente ciertas. Qué sistema usa más memoria depende de muchos factores; la presencia o ausencia de un compilador JIT es un factor, pero no siempre es significativo.

+0

No estoy de acuerdo con su oración "Si el uso de memoria dominante de un programa es el código en sí, entonces un compilador JIT agrega gran sobrecarga de memoria ...": esto es falso para un compilador JIT de zona activa bien diseñado. También estoy en desacuerdo con su oración "Si el uso dominante de la memoria es estructuras de datos del programa, entonces [...] PyPy usa mucha menos memoria que CPython" - PyPy NO es tan bueno. –

+0

@Atom Un compilador JIT traduce código a código en tiempo de ejecución. Un compilador JIT especializado * debe * también mantener el código original (un compilador JIT no especializado no es demasiado interesante, ya que podría implementarse como un compilador anticipado, ganando eficiencia de no tener que ejecutarlo en tiempo de ejecución y la capacidad de dedicar más tiempo a las optimizaciones). Por lo tanto, debe agregar * como mínimo una sobrecarga espacial O (n), donde n es la cantidad de código compilado por el compilador JIT. Además de la memoria del JIT en sí ... – Ben

+0

@Atom Es cierto que generalmente el JIT no compila la mayor parte del programa, por lo que posiblemente exagere el caso. Pero la cantidad de código de un programa compilada en JIT siempre va a depender del programa. Es cierto que para cualquier sistema JIT dado hay programas que pagarán una gran cantidad de gastos de memoria en comparación con el mismo programa que se ejecuta en un entorno no JIT. – Ben

Cuestiones relacionadas