2009-03-02 16 views
36

Qual è la differenza tra il compilatore JIT e CLR? Se compilate il vostro codice su il e CLR esegue quel codice, allora che cosa sta facendo il JIT? Come è cambiata la compilazione JIT con l'aggiunta di generici al CLR?CLR vs JIT

+0

Ho arricchito la mia risposta da quando l'hai accettata. Se questo lo rende troppo prolisso e non è più quello che considereresti una risposta accettabile, aggiungi un commento per dirlo e lo ridurrò/ripristinalo. Mi è sembrato un peccato perdere le informazioni dalle altre risposte – ShuggyCoUk

risposta

42

JIT è un aspetto della CLR.

In particolare è la parte responsabile della modifica di CIL/MSIL (di seguito denominato IL) prodotto dal compilatore della lingua originale (csc.exe per Microsoft C# per esempio) in codice macchina nativo per il processore corrente (e architettura che espone nel processo corrente, ad esempio 32/64 bit). Se l'assembly in questione non era valido, il processo JIT non è più necessario e CLR eseguirà questo codice senza l'uso di esso.

Prima di utilizzare un metodo che non è ancora stato convertito dalla rappresentazione intermedia, è responsabilità del JIT convertirlo.
Esattamente il JIT esegue il kick in è specifico per l'implementazione e soggetto a modifiche. Tuttavia, il progetto CLR impone che il JIT avvenga prima del il codice pertinente venga eseguito, le JVM al contrario sarebbero libere di interpretare il codice per un po 'mentre un thread separato crea una rappresentazione di codice macchina.
Il CLR "normale" utilizza uno pre-JIT stub approach dove i metodi vengono compilati JIT solo quando vengono utilizzati. Questo implica che lo stub del metodo nativo iniziale sia un riferimento indiretto per istruire il JIT a compilare il metodo, quindi modificare la chiamata originale per saltare lo stub iniziale. L'edizione compatta corrente invece compila tutti i metodi su un tipo quando viene caricato.

Per indirizzare l'aggiunta di Generics.

Questo è stato l'ultimo importante cambiamento alle specifiche IL e JIT in termini di semantica rispetto ai dettagli di implementazione interni.

Sono state aggiunte diverse nuove istruzioni IL e sono state fornite più opzioni di metadati per i tipi di strumenti e i membri. I vincoli sono stati aggiunti anche a livello di IL.

Quando il JIT compila un metodo che ha argomenti generici (esplicitamente o implicitamente attraverso la classe contenitore), può impostare percorsi di codice diversi (istruzioni del codice macchina) per ciascun tipo utilizzato.In pratica, il JIT utilizza un'implementazione condivisa per tutti i tipi di riferimento in quanto le variabili per questi mostreranno la stessa semantica e occuperanno lo stesso spazio (IntPtr.Size).

Ogni tipo di valore riceverà un codice specifico generato, trattando la dimensione ridotta/aumentata delle variabili sullo stack/heap è una delle ragioni principali. Inoltre, emettendo l'opcode vincolato prima che il metodo invochi molte chiamate su tipi non di riferimento, non è necessario specificare il valore per chiamare il metodo (questa ottimizzazione viene utilizzata anche in casi non generici). Ciò consente inoltre che il comportamento predefinito <T> venga gestito correttamente e che i confronti nulli vengano eliminati come non operativi (sempre false) quando viene utilizzato un tipo di valore non Nullable.

Se viene eseguito un tentativo in runtime per creare un'istanza di un tipo generico tramite riflessione, i parametri di tipo verranno convalidati dal runtime per garantire che superino eventuali vincoli. Ciò non influisce direttamente sul JIT a meno che non venga utilizzato all'interno del sistema di tipi (improbabile anche se possibile).

64

Si compila il codice in IL che viene eseguito e compilato in codice macchina durante il runtime, questo è ciò che viene chiamato JIT.

Modifica, per rimpolpare la risposta un po 'di più (ancora eccessivamente semplificato):

Quando si compila il codice C# in Visual Studio che venga trasformato in IL che il CLR capisce, l'IL è lo stesso per tutte le lingue in esecuzione su CLR (che è ciò che consente al runtime .NET di utilizzare più lingue e inter-op tra di loro facilmente).

Durante il runtime, l'IL viene interpretato in codice macchina (che è specifico dell'architettura in cui ci si trova) e quindi viene eseguito. Questo processo è chiamato compilazione Just In Time o JIT in breve. Solo l'IL che è necessario viene trasformato in codice macchina (e solo una volta, è "memorizzato nella cache" una volta compilato in codice macchina), appena in tempo prima di essere eseguito, da qui il nome JIT.

Questo è ciò che sarebbe simile a C#

C# Codice > compilatore C# > IL > .NET Runtime > compilatore JIT > codice macchina > Esecuzione

E questo è ciò che apparirebbe come per VB

VB codice > VB Compiler > IL > .NET Runtime > compilatore JIT > codice macchina > Esecuzione

E come si può vedere solo i due primi passi sono unici per ogni lingua, e tutto ciò dopo che è stato trasformato in IL è la stessa che è, come ho detto prima, il motivo per cui è possibile eseguire diverse lingue su .NET.

+2

-1 per il riferimento a IL come bytecode, è una semantica di Java. IL (ex MSIL) è il termine corretto non confondere i due. Cambia questo e hai il mio voto. –

+0

@ John Leidegren: buon punto, cambiato. – thr

+0

È vero che la JIT compila il codice al codice macchina la prima volta che si esegue il programma, dopodiché la compilazione viene saltata e viene utilizzato il codice compilato? Se è così potrebbe valere la pena di incorporare questo nella tua risposta. –

23

Il JIT è fondamentalmente parte del CLR. Il netturbino è un altro. Piuttosto dove si mettono le responsabilità di interoperabilità, ecc. È un'altra questione, e quella in cui sono enormemente sottovalutato per commentare :)

+1

@Ted: era questo il tipo di cosa che ti interessava? Non ho fornito una spiegazione più dettagliata (come quella di Fredrik) perché pensavo che tu sapessi già la maggior parte di questo genere di cose e che fossi interessato alla relazione tra il CLR e il JIT. –

+0

No, non ho mai votato. Penso che tutte le risposte siano davvero buone. Penso che avrei dovuto porre la domanda in modo diverso. Ero davvero interessato alla relazione tra il CLR e il compilatore JIT e come è cambiato con l'aggiunta di generici. –

27

Come dice Jon Skeet, JIT fa parte del CLR. Fondamentalmente questo è ciò che sta accadendo sotto il cofano:

  1. Il codice sorgente viene compilato in un bytecode sapere come linguaggio intermedio comune (CIL).
  2. I metadati di ogni classe e ogni metodo (e ogni altra cosa: O) sono inclusi nell'intestazione PE dell'eseguibile risultante (sia esso una dll o un exe).
  3. Se si sta eseguendo un eseguibile, l'intestazione PE include anche un bootstrapper convenzionale che si occupa del caricamento del CLR (Common Language Runtime) quando si esegue l'eseguibile.

Ora, quando si esegue:

  1. Il bootstraper inizializza il CLR (principalmente caricando il gruppo mscorlib) e istruisce per eseguire il montaggio.
  2. CLR esegue la voce principale.
  3. Ora, le classi hanno una tabella vettoriale che contiene gli indirizzi delle funzioni del metodo, in modo che quando si chiama MyMethod, questa tabella viene cercata e quindi viene effettuata una chiamata corrispondente all'indirizzo. All'inizio TUTTE le voci per tutte le tabelle hanno l'indirizzo del compilatore JIT.
  4. Quando viene effettuata una chiamata a uno di questi metodi, viene richiamata la JIT anziché il metodo effettivo e assume il controllo. Il JIT quindi compila il codice CIL in codice assembly reale per l'architettura appropriata.
  5. Una volta compilato il codice, il JIT entra nella tabella vettoriale del metodo e sostituisce l'indirizzo con quello del codice compilato, in modo che ogni chiamata successiva non richiami più il JIT.
  6. Infine, il JIT gestisce l'esecuzione al codice compilato.
  7. Se si chiama un altro metodo che non sono ancora in fase di compilazione poi tornare a 4 ... e così via ...
+1

Dannazione! Smettila di chiamarlo bytecode, è IL, una rappresentazione linguistica intermedia. Poiché le dimensioni delle istruzioni IL sono parole a 16 bit. –

+1

Temo che stai combattendo una battaglia persa su questo John :) Penso che "codice intermedio" sia un termine generico ragionevole in cui vuoi includere java, 'net's, LLVM ecc. Ma danneggi se il bytecode non è scattante ... – ShuggyCoUk

+0

Se parli di codice byte, presumo che tu stia parlando di un bytecode Java. Se dici IL, presumo che tu stia parlando della piattaforma .NET. E 'così semplice. Voglio mantenere viva questa distinzione. –

15

So che il thread è piuttosto vecchio, ma ho pensato di poter inserire l'immagine che mi ha fatto capire JIT. È dal libro eccellente CLR via C# by Jeffrey Ritcher. Nella foto, i metadati di cui sta parlando è il metadati emessa nell'intestazione di assemblaggio dove sono conservate tutte le informazioni sui tipi in assemblea:

JIT image from CLR via C#

2

1) durante la compilazione del programma di .net, programma di .net il codice viene convertito in codice Intermediate Language (IL)

2) dopo l'esecuzione del programma il codice di lingua intermedio viene convertito nel codice operativo del sistema operativo come e quando viene chiamato un metodo; questa è chiamata compilazione JIT (Just in Time).

-2
  1. Common Language Runtime (CLR) è l'interprete mentre Just In Time (JIT) è un compilatore in .Net Framework.

2.JIT è il compilatore interno di .NET che prende codice Microsoft Intermediate Language codice (MSICL) dal CLR e lo esegue le istruzioni specifiche della macchina mentre CLR funziona come motore il suo compito principale è quello di fornire il codice a MSICL JIT per garantire che il codice sia completamente compilato secondo le specifiche della macchina.

+0

Micro ** S ** oft? Perché? –