2010-07-21 25 views
44

Un programa .NET se compila primero en código MSIL. Cuando se ejecuta, el compilador JIT lo compilará en código máquina nativo.¿Dónde se almacena en caché el código .NET JIT-compiled?

Me pregunto:

donde se almacena estos código máquina compilado JIT? ¿Está solo almacenado en el espacio de direcciones del proceso? Pero dado que el segundo inicio del programa es mucho más rápido que la primera vez, creo que este código nativo debe haber sido almacenado en un disco en algún lugar, incluso después de que la ejecución haya finalizado. ¿Pero donde?

Respuesta

69

memoria. Es puede ser almacenado en caché, ese es el trabajo de ngen.exe. Genera una versión .ni.dll del ensamblado, que contiene código de máquina y se almacena en el GAC. Que automáticamente se carga después, pasando por alto el paso JIT.

Pero eso tiene poco que ver con por qué su programa comienza más rápido la 2da vez. La primera vez que tiene un llamado "arranque en frío".Que está completamente dominado por el tiempo dedicado a encontrar los archivos DLL en el disco duro. La segunda vez que tiene un inicio cálido, los archivos DLL ya están disponibles en el caché del sistema de archivos.

Los discos son lentos. Una SSD es una solución obvia.

Fwiw: este no es un problema exclusivo del código administrado. Grandes programas no administrados con muchos DLL lo tienen también. Dos ejemplos canónicos, presentes en la mayoría de las máquinas de desarrollo son Microsoft Office y Acrobat Reader. Ellos hacen trampa. Cuando se instalan, ponen un "optimizador" en la clave de registro Ejecutar o en la carpeta Inicio. Todo lo que hacen estos optimizadores es cargar todas las DLL que usa el programa principal y luego salir. Esto prepara el caché del sistema de archivos, cuando el usuario utiliza el programa posteriormente, se iniciará rápidamente ya que su inicio en caliente es rápido.

Personalmente, esto me resulta extraordinariamente molesto. Porque lo que realmente hacen es ralentizar cualquier otro programa que pueda querer iniciar después de iniciar sesión. Lo cual rara vez es Office o Acrobat. Debo eliminar estos optimizadores, repetidamente si es necesario cuando una actualización arruinada lo devuelve.

Puede usar este truco también, pero úselo de manera responsable, por favor.

+17

Vista y Windows 7 tienen integrado este truco de caché de DLL, por lo que ya no necesita hacer "aceleradores de aplicaciones". Superfetch registra qué aplicaciones usa más y leerá esos archivos después del inicio. Es mejor que una aplicación de acelerador porque presta atención al uso actual de la memoria y al uso real de la aplicación. –

+1

@Hans: Usted dijo '" Genera una versión .ni.dll del ensamblado, que contiene código de máquina y se almacena en el GAC "'. Tengo algunas dudas ... GAC es solo para almacenar asambleas públicas, ¿verdad? ¿Se almacena una 'imagen nativa' de un' exe' que estoy ejecutando? – Sreekumar

+0

Sí, eso es lo que dice la respuesta. Está oculto a la vista, pero puede verlo iniciando el símbolo del sistema. Escriba 'dir c: \ windows \ assembly' para listar los directorios en el GAC. –

2

En resumen, la IL es JIT-compilado para cada invocación del programa y se mantiene en páginas de códigos del espacio de direcciones del proceso. Consulte el Capítulo 1 de Richter para obtener una gran cobertura del modelo de ejecución de .NET.

1

Creo que el código compilado JIT nunca se almacena o intercambia de memoria. El aumento de rendimiento que percibe en una segunda ejecución de un ensamblaje se debe a que los ensamblajes dependientes ya están en memoria o en el caché de disco.

+0

Solo los controladores del núcleo pueden evitar que el código se cancele. El código compilado JIT se puede paginar como cualquier otra página en la memoria de la aplicación. –

7

JIT código máquina compilado se almacena en caché en la memoria per-método, cada vez que se ejecuta un método para la primera vez. No creo que alguna vez se guarde en caché en el disco.

Es posible que el proceso sea más rápido de cargar la segunda vez porque Windows guardó en caché (en memoria) los archivos utilizados por su proceso (dlls, recursos, etc.) en la primera ejecución. En la segunda ejecución, no es necesario ir al disco, donde esto puede haberse hecho en la primera ejecución.

Puede confirmar esto por running NGen.exe para realmente compilar previamente el código de máquina para su arquitectura, y comparar el rendimiento de la primera y la segunda ejecución. Mi apuesta es que la segunda ejecución sería aún más rápida, debido al almacenamiento en caché en el sistema operativo.

+0

¿Sabe dónde windows está almacenando estos archivos en caché usados ​​por proceso (dlls, recursos, etc.)? – Sreekumar

+0

@Sreekumar: En RAM, al igual que casi cualquier otro sistema operativo en estos días. – SamB

11

Como han señalado otros, el código está JIT por proceso en su caso, y no está almacenado en caché: la aceleración que está viendo en la segunda carga es el almacenamiento en memoria caché de disco del sistema operativo (es decir, en memoria) las asambleas.

Sin embargo, mientras que no hay almacenamiento en caché (aparte de caché de disco OS) en la versión de servidor de escritorio \ del marco, no hay almacenamiento en caché de código de máquina JIT'd en otra versión del marco.

De interés es lo que está sucediendo en el .NET Compact Framework (NETCF para Windows Phone 7 relase). Los avances recientes permiten compartir el código de un marco de JIT entre procesos en los que el código JIT está almacenado. Esto se ha llevado a cabo principalmente para un mejor rendimiento (tiempo de carga y uso de memoria) en dispositivos restringidos, como teléfonos móviles.

Respondiendo a la pregunta, no hay un caché de marco directo del código JIT en la versión de escritorio \ servidor del CLR, pero sí en la última versión del marco compacto, es decir, NETCF.

Referencia: creemos en el intercambio de

http://blogs.msdn.com/b/abhinaba/archive/2010/04/28/we-believe-in-sharing.aspx

1

Sí, NGEN.EXE colocará una versión compilada JIT de un ejecutable .NET en el GAC, incluso cuando la versión MSIL no está allí. Lo he intentado, pero fue en vano. Creo que, a menos que la versión original de MSIL también esté en el GAC y se cargue desde allí, la versión JIT del GAC no se utilizará. También creo que las compilaciones JIT sobre la marcha (no NGEN) nunca se almacenan en caché; solo ocupan el proceso de memoria.

Creo que esto al leer el documento MS y de varios experimentos. Agradecería una confirmación o refutación de mis afirmaciones de aquellos "que saben".

Cuestiones relacionadas