Il titolo riassume molto ma mi chiedevo perché sistemi come .net compilano il codice ogni volta che viene eseguito invece di compilarlo una sola volta sul computer di destinazione?Perché .net usa un compilatore JIT invece di compilare il codice una sola volta sul computer di destinazione?
risposta
Ci sono due cose che si possono ottenere utilizzando un formato intermedio come Java o .NET:
- È possibile eseguire il programma su qualsiasi piattaforma, proprio perché il codice è rappresentato in un formato intermedio invece di natale codice. Hai solo bisogno di scrivere un interprete per il formato intermedio.
- Esso consente per alcune ottimizzazioni di runtime che non sono (facilmente) possibile al momento della compilazione: per esempio, è possibile sfruttare le caratteristiche speciali sui nuovi processori, anche se non ci fossero queste CPU quando hai scritto il programma - solo il compilatore JIT deve saperlo.
Ora, per quanto riguarda il motivo per cui si potrebbe non voler eseguire la compilazione alla prima esecuzione e quindi solo memorizzarla nella cache - ci possono essere anche un paio di motivi.
Se si compila prima dell'avvio, l'utente deve attendere molto più tempo per quella prima esecuzione - in quel momento, non si può sapere cosa l'utente effettivamente utilizzerà. Compilando solo ciò di cui hai bisogno, quando ne hai bisogno, puoi iniziare molto più rapidamente, semplicemente perché hai meno lavoro da fare e non immagazzini tanto codice che l'utente non userà mai (che per un grande programma può essere un sacco di codice).
Se si avvia il caching del codice JIT attraverso le sessioni, è necessario tenere traccia di ciò che è già stato compilato e quindi memorizzarlo su disco. Per un programma di grandi dimensioni, potresti avere un sacco di codice nativo da caricare dal disco. I/O del disco sono piuttosto costosi, quindi potrebbe essere necessario più tempo per attendere il disco piuttosto che ridirigerlo. Inoltre, è necessario tenere traccia di quanto tempo è utilizzabile. Se l'hardware cambia, potresti voler re-JIT per applicare alcune nuove ottimizzazioni. Se il programma cambia, non puoi usare nessuno dei tuoi vecchi codici compilati. Se il compilatore di runtime cambia, potrebbe essere stato corretto un errore di sicurezza e sarà necessario ricompilare per assicurarsi che il bug non rimanga nel codice nativo.
Fondamentalmente, il compilatore JIT ha improvvisamente molto più lavoro da fare (incluso l'I/O del disco per gestire la cache) e diventa molto più complicato e lento, riducendo il punto di JIT'ing.
Ora, ciò non significa che a volte non sia vantaggioso compilarlo preconfigurato, e come sottolinea Matthew Ferreira, questo è ciò che lo strumento ngen può fare - ma nel caso generale, non è solo vale la pena farlo, perché la compilazione JIT è spesso più che abbastanza veloce.
# 1 è probabilmente il singolo motivo più importante – STW
Nessuno di questi punti è pertinente alla domanda: atli ha chiesto di compilarlo sul computer di destinazione, non sul computer dello sviluppatore. – JasonFruit
@Jason: Ah, hai ragione - ho interpretato male quella parte. Modifica ... –
Cosa succede se si sposta l'eseguibile su un'altra macchina? Se fosse stato compilato una volta per il processore specifico della prima macchina, non sarebbe in grado di sfruttare un set di istruzioni (possibilmente) più avanzato o efficiente disponibile sul nuovo processore. Se si desidera compilare una volta sul computer di destinazione, considerare l'utilizzo di ngen.exe durante l'installazione dell'applicazione.
Non scrivo compilatori o run-time, quindi non posso dirlo con certezza, ma non credo che sia just-in-time = ogni volta. Significa solo che aspettiamo di aver davvero bisogno di compilare, ma una volta che la compilazione è stata fatta per quell'istanza, non verrà più compilata.
Sei corretto: se un pezzo di codice non viene eseguito durante una sessione, non è necessario che sia compilato JIT. Tuttavia, il codice compilato JIT non è (solitamente) memorizzato nella cache per le sessioni future, quindi la compilazione JIT si ripeterà la volta successiva che si esegue il programma. –
@ Michael Che non è corretto. NGen memorizza nella cache il codice compilato JIT per il riutilizzo futuro. –
Se si compila direttamente alla macchina di codice, allora hai scelto come target un sistema specifico:
Code --> Machine Code
Tuttavia, in .NET, Java, etc.quello che stai prendendo di mira è la macchina virtuale . Questo produce codice che qualsiasi VM conforme a .NET può interpretare e, a sua volta, JIT in codice macchina reale.
Così, in .NET:
Code --> IL --> VM (executing) --> JIT'd Machine Code
Inizialmente sembra più complicato, ma come targeting più architetture:
Code(x86) --> Machine Code(x86) Code(ppc) --> Machine Code(ppc) etc... (1x code-set per target)
Versus
Code --> IL --> VM(x86) (executing) --> JIT'd x86 Machine Code VM(ppc) (executing) --> JIT'd ppc Machine Code etc...
La mia illustrazione è ruvida, ma noterai che un singolo pacchetto di codice .NET può essere indirizzato e eseguito su più piattaforme
Un altro vantaggio della compilazione JIT: il codice che è stato scritto 10 o 15 anni fa può ottenere un significativo incremento delle prestazioni semplicemente eseguendo una JIT avanzata, senza alcuna modifica del codice.
Tuttavia, CLR potrebbe facilmente includere un numero di versione nell'ipotetica versione JIT del cache memorizzata sul disco dell'assembly ed eliminarlo la prima volta che viene eseguito su un CLR aggiornato. – binki
Il titolo praticamente riassume, ma mi chiedevo perché sistemi come .net compilano il codice ogni volta che viene eseguito invece di compilarlo una sola volta sul computer di destinazione?
.NET fa cache i risultati di compilazione CIL in codice nativo su un determinato obiettivo, ma questo non è banale:
- esiste un trade-off tra il caricamento nella cache i dati dal disco e ricompilare on- il volo.
- Qualsiasi forma di generazione di codice in fase di esecuzione richiede la possibilità di compilare al volo. Questo non è solo l'uso di
System.Reflection.Emit
ma anche la reificazione dei tipi da assiemi caricati dinamicamente e anche la creazione di nuovi tipi di valore durante la ricorsione polimorfica.
Il fatto che 'Expression
- 1. Le app .NET Core richiedono il runtime .NET installato sul computer di destinazione?
- 2. Perché il codice JIT della cache JIT non è compilato?
- 3. perché usa il movl invece di premere?
- 4. Scrivere un compilatore JIT nell'assemblaggio
- 5. È possibile scrivere un compilatore JIT (in codice nativo) interamente in un linguaggio .NET gestito
- 6. Perché il costruttore viene chiamato una sola volta?
- 7. Cosa fa un compilatore JIT?
- 8. Codice JIT .NET Cache che perde?
- 9. Chiama il codice Python da LLVM JIT
- 10. Installa Valgrind su un computer PowerPC di destinazione
- 11. Come si usa CGAffineTransformMakeScale e Rotation in una sola volta?
- 12. SICStus Prolog Compilatore JIT
- 13. Perché UnderscoreJS usa toString.call() invece di typeof?
- 14. Come il codice Java "duplicato" è ottimizzato dal compilatore JIT JIT?
- 15. Come si esegue il codice una sola volta e solo una volta in Swift?
- 16. Perché il compilatore non può compilare semplicemente il mio codice mentre lo digito?
- 17. Perché ho bisogno di un compilatore C++ per compilare Rust?
- 18. Quando ha ottenuto Java un compilatore JIT?
- 19. L'animazione funziona una sola volta
- 20. Perché mmap() usa MAP_FAILED invece di NULL?
- 21. Dove si trova esattamente .NET Runtime (CLR), Compilatore JIT?
- 22. facendo clic sul pulsante una sola volta (js)
- 23. Come selezionare il framework di destinazione di un compilatore CodeDom utilizzando C#?
- 24. Configurazione di IIS sul computer dell'utente tramite il codice C#
- 25. RecyclerView.onBindViewHolder chiamato una sola volta
- 26. JIT CLR .NET compila ogni metodo ogni volta?
- 27. Perché memo.Lines usa TStrings invece di TStringList?
- 28. Perché Forth usa l'istruzione IF THEN ... invece di ENDIF?
- 29. Focus una sola volta - Jquery
- 30. In teoria, posso ottenere il JIT openJDK e compilare il mio codice Java in nativo?
La maggior parte delle risposte non ha letto attentamente la domanda. Sta chiedendo: perché la macchina di destinazione non può fare una volta la compilation e tenerla (non: perché non possiamo compilare una volta e distribuire il file binario) – egrunin
Funziona già in questo modo. Guarda attraverso i servizi installati sul tuo computer. Il servizio "NGEN di Microsoft .NET Framework" entra in azione per la precompilazione degli assembly. Se opportunamente solleticato da un installatore. –
Non si compila ogni volta che viene eseguito. Quando un metodo viene compilato con JIT, il codice nativo generato viene archiviato nella cache di immagini native. Nelle esecuzioni successive se il runtime vede che un metodo è già stato compilato, non lo ricompone di nuovo. – mhenry1384