Pregunta

¿Cuál es la diferencia entre el compilador JIT y CLR?Si compila su código en il y CLR ejecuta ese código, ¿qué está haciendo el JIT?¿Cómo ha cambiado la compilación JIT con la adición de genéricos al CLR?

¿Fue útil?

Solución

El JIT es un aspecto del CLR.

Específicamente, es la parte responsable de cambiar CIL / MSIL (en adelante, IL) producido por el compilador del idioma original (csc.exe para Microsoft c # por ejemplo) en código de máquina nativo del procesador actual (y la arquitectura que expone en el proceso actual, por ejemplo 32 / 64bit). Si el ensamblaje en cuestión fue identificado, entonces el proceso JIT es completamente innecesario y el CLR ejecutará este código perfectamente sin él.

Antes de utilizar un método que aún no se ha convertido de la representación intermedia, es responsabilidad del JIT convertirlo.
Exactamente cuándo se activará el JIT es específico de la implementación y está sujeto a cambios. Sin embargo, el diseño de CLR exige que el JIT ocurra antes de que se ejecute el código relevante, en contraste, los JVM serían libres de interpretar el código por un tiempo, mientras que un hilo separado crea una representación de código de máquina.
El CLR 'normal' utiliza un enfoque de código auxiliar anterior a JIT donde por métodos los JIT se compilan solo cuando se usan. Esto implica que el apéndice del método nativo inicial sea una indirecta para indicar al JIT que compile el método y luego modifique la llamada original para saltear el apéndice inicial. En cambio, la edición compacta actual compila todos los métodos en un tipo cuando se carga.

Para abordar la adición de genéricos.

Este fue el último cambio importante en la especificación IL y JIT en términos de su semántica en comparación con los detalles de su implementación interna.

Se agregaron varias instrucciones IL nuevas y se proporcionaron más opciones de metadatos para los tipos de instrumentos y los miembros. También se agregaron restricciones a nivel de IL.

Cuando el JIT compila un método que tiene argumentos genéricos (ya sea explícita o implícitamente a través de la clase que lo contiene), puede configurar diferentes rutas de código (instrucciones de código de máquina) para cada tipo utilizado. En la práctica, el JIT utiliza una implementación compartida para todos los tipos de referencia ya que las variables para estos exhibirán la misma semántica y ocuparán el mismo espacio (IntPtr.Size).

Cada tipo de valor obtendrá un código específico generado para él, y el hecho de que el tamaño reducido / aumentado de las variables en la pila / montón sea una razón importante para esto. Además, al emitir el código de operación restringido antes de las llamadas al método, muchas invocaciones en tipos que no son de referencia no necesitan encuadrar el valor para llamar al método (esta optimización también se usa en casos no genéricos). Esto también permite que el comportamiento predeterminado de <T> se maneje correctamente y que las comparaciones sean nulas y se eliminen como sin operaciones (siempre falsas) cuando se usa un tipo de valor no Nullable.

Si se realiza un intento en tiempo de ejecución para crear una instancia de un tipo genérico mediante reflexión, los parámetros de tipo serán validados por el tiempo de ejecución para garantizar que superen cualquier restricción. Esto no afecta directamente al JIT a menos que se use dentro del sistema de tipos (aunque sea poco probable)

Otros consejos

Usted compila su código en IL, que se ejecuta y compila en código de máquina durante el tiempo de ejecución, esto es lo que se llama JIT.

Editar, para desarrollar un poco más la respuesta (aún demasiado simplificada):

Cuando compila su código C# en Visual Studio, se convierte en IL que CLR entiende, IL es el mismo para todos los lenguajes que se ejecutan sobre CLR (que es lo que permite que el tiempo de ejecución de .NET use varios lenguajes e interoperabilidad). entre ellos fácilmente).

Durante el tiempo de ejecución, el IL se interpreta en código de máquina (que es específico de la arquitectura en la que se encuentra) y luego se ejecuta.Este proceso se llama compilación Just In Time o JIT para abreviar.Sólo el IL que se necesita se transforma en código de máquina (y sólo una vez, se "almacena en caché" una vez que se compila en código de máquina), justo a tiempo antes de que se ejecute, de ahí el nombre JIT.

Así es como se vería para C#

Código C# > Compilador C# > ILLINOIS > Tiempo de ejecución .NET > Compilador JIT > Codigo de maquina > Ejecución

Y así es como se vería para VB.

Código VB > Compilador VB > ILLINOIS > Tiempo de ejecución .NET > Compilador JIT > Codigo de maquina > Ejecución

Y como puede ver, solo los dos primeros pasos son únicos para cada idioma, y ​​todo después de convertirse en IL es igual, lo cual es, como dije antes, la razón por la que puede ejecutar varios idiomas diferentes sobre .NET.

Como dice Jon Skeet, JIT es parte del CLR. Básicamente, esto es lo que sucede debajo del capó:

  1. Su código fuente se compila en un código de bytes conocido como el lenguaje intermedio común (CIL).
  2. Los metadatos de cada clase y cada método (y todo lo demás: O) se incluye en el encabezado PE del ejecutable resultante (ya sea un dll o un exe).
  3. Si está produciendo un ejecutable, el encabezado PE también incluye un programa de arranque convencional que se encarga de cargar el CLR (Common Language Runtime) cuando ejecuta su ejecutable.

Ahora, cuando ejecutas:

  1. El programa de arranque inicializa el CLR (principalmente cargando el ensamblado mscorlib) y le indica que ejecute su ensamblaje.
  2. El CLR ejecuta su entrada principal.
  3. Ahora, las clases tienen una tabla de vectores que contiene las direcciones de las funciones del método, de modo que cuando llama a MyMethod, se busca esta tabla y luego se realiza una llamada correspondiente a la dirección. Al comenzar, TODAS las entradas para todas las tablas tienen la dirección del compilador JIT.
  4. Cuando se realiza una llamada a uno de estos métodos, se invoca el JIT en lugar del método real y toma el control. El JIT luego compila el código CIL en el código de ensamblaje real para la arquitectura apropiada.
  5. Una vez que se compila el código, el JIT entra en la tabla de vectores de métodos y reemplaza la dirección con la del código compilado, de modo que cada llamada posterior ya no invoca el JIT.
  6. Finalmente, el JIT maneja la ejecución del código compilado.
  7. Si llama a otro método que aún no se ha compilado, vuelva a 4 ... y así sucesivamente ...

El JIT es básicamente parte del CLR. El recolector de basura es otro. El lugar en el que pones responsabilidades de interoperabilidad, etc., es otro asunto, y uno en el que estoy muy poco calificado para comentar :)

Sé que el hilo es bastante antiguo, pero pensé que podría poner en la imagen que me hizo entender JIT. Es del excelente libro CLR a través de C # de Jeffrey Ritcher . En la imagen, los metadatos de los que está hablando son los metadatos emitidos en el encabezado del ensamblaje donde se almacena toda la información sobre los tipos en el ensamblaje:

Imagen JIT desde CLR a través de C #

1) al compilar el programa .net, el código del programa .net se convierte en código de lenguaje intermedio (IL)

2) al ejecutar el programa, el código de idioma intermedio se convierte en código nativo del sistema operativo cuando se llama a un método; esto se llama compilación JIT (Just in Time).

  1. Common Language Runtime (CLR) es un intérprete mientras que Just In Time (JIT) es un compilador en .Net Framework.

2.JIT es el compilador interno de .NET que toma el código del lenguaje de código intermedio MicroSoft (MSICL) de CLR y lo ejecuta en instrucciones específicas de la máquina, mientras que CLR funciona como un motor, su tarea principal es proporcionar el código MSICL a JIT para garantizar ese código está completamente compilado según las especificaciones de la máquina.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top