2009-08-10 20 views

risposta

42

Nota: questa risposta è in un contesto "per esecuzione".Il codice è normalmente JITted ogni volta che si esegue il programma. Utilizzando ngen o .NET Native cambiamenti che la storia, anche ...

differenza HotSpot, il CLR JIT compila sempre esattamente una volta per ciclo. Non interpreta mai e non ricompila mai con un'ottimizzazione più pesante di prima basata sull'utilizzo effettivo.

Questo può cambiare, ovviamente, ma è stato così perché v1 e non mi aspetto che cambi presto.

Il vantaggio è che rende il JIT molto più semplice - non c'è bisogno di prendere in considerazione il codice "vecchio" che è già in esecuzione, annullare ottimizzazioni sulla base di premesse che non sono più validi, ecc

Un punto a. Il favore di NET è che la maggior parte dei linguaggi CLR rende i metodi non virtuali di default, il che significa che si può fare molto più inlining. HotSpot può inlineare un metodo fino a quando non viene prima sovrascritto, a quel punto annulla l'ottimizzazione (o qualche cosa intelligente in alcuni casi per usare ancora condizionatamente il codice inline, in base al tipo effettivo). Con meno metodi virtuali di cui preoccuparsi, .NET può ignorare il dolore di non essere in grado di allineare nulla di virtuale.

MODIFICA: Quanto sopra descrive la struttura del desktop. Il Compact Framework cancella il codice nativo quando lo desidera, JITting di nuovo se necessario. Tuttavia, questo non è ancora come l'ottimizzazione adattiva HotSpots.

Il micro quadro non sembra affatto JIT, interpretando invece il codice. Questo ha senso per i dispositivi molto limitati. (Non posso dire di sapere molto sul framework micro.)

+0

Vedo ... quindi l'unica volta che il CLR .Net viene eseguito in modalità interpretata è se il JIT è completamente disattivato (per il debug). – jsight

+3

Non credo che interpreti effettivamente il codice anche allora - il debugger è in grado di scorrere il codice compilato in modo appropriato, questo è tutto. Mono * ha * però un interprete. –

+1

Curiosamente, .net MF (MicroFramework per dispositivi embedded) interpreta IL invece di compilarlo. –

14

Il runtime .NET compila sempre il codice JIT prima dell'esecuzione. Quindi, non è mai interpretato.

È possibile trovare una lettura più interessante in CLR Design Choices con Anders Hejlsberg. Soprattutto la parte:

Ho letto che Microsoft ha deciso che IL verrà sempre compilato, mai interpretato. In che modo le informazioni sul tipo di codifica contenute nelle istruzioni aiutano gli interpreti a funzionare in modo più efficiente?

Anders Hejlsberg: Se un interprete può fare ciecamente ciò che dicono le istruzioni senza dover tenere traccia di ciò che è in cima alla pila, può andare più veloce. Quando vede un iadd, ad esempio, l'interprete non deve prima capire quale tipo di aggiunta è, sa che è un numero intero. Supponendo che qualcuno abbia già verificato che lo stack ha un aspetto corretto, è sicuro di dedicare un po 'di tempo lì, e ti interessa per un interprete. Nel nostro caso, tuttavia, non abbiamo mai inteso indirizzare uno scenario interpretato con il CLR. Intendevamo sempre JIT [compilazione just-in-time], e ai fini del JIT, dovevamo comunque tenere traccia delle informazioni sul tipo. Dato che abbiamo già le informazioni sul tipo, in realtà non ci compra nulla per metterlo nelle istruzioni.

Bill Venners: molte JVM moderne [macchine virtuali Java] fanno ottimizzazione adattiva, dove iniziano interpretando bytecode. Profilano l'app mentre corre a trovare il 10% - 20% del codice che viene eseguito dall'80% al 90% delle volte, quindi lo compilano in formato nativo. Tuttavia, essi non necessariamente compilano questi bytecode solo in tempo. I bytecode di un metodo possono ancora essere eseguiti dall'interprete mentre vengono compilati in nativi e ottimizzati in background. Quando il codice nativo è pronto, può sostituire i bytecode. Non mirando a uno scenario interpretato, hai completamente escluso questo approccio all'esecuzione in un CLR?

Anders Hejlsberg: No, non l'abbiamo completamente escluso. Possiamo ancora interpretare. Non siamo ottimizzati per l'interpretazione. Non siamo ottimizzati per scrivere quell'interprete dalle prestazioni elevate che interpreterà sempre e solo. Non penso che nessuno lo faccia più. Per un set top box 10 anni fa, sarebbe stato interessante. Ma non è più interessante. Le tecnologie JIT sono arrivate al punto in cui è possibile avere più possibili strategie JIT. Si può anche immaginare di usare un JIT veloce che strappa rapidamente, e poi quando scopriamo che stiamo eseguendo un metodo particolare per tutto il tempo, usando un altro JIT che impiega un po 'più di tempo e fa un miglior lavoro di ottimizzazione. C'è molto di più che puoi fare in JIT.

0

Non ci credo, e non penso che dovrebbe mai.

In che modo la squadra JIT può sapere quante volte verrà chiamato un metodo particolare? Non sarebbe la frequenza del fattore di interpretazione nella decisione?

Vorrei anche mettere in discussione quanto un compilatore JIT sarebbe in grado di analizzare una funzione per determinare se l'interpretazione sarebbe la migliore senza interpretare la funzione stessa. E dato questo fatto (che almeno un passaggio del metodo ha avuto luogo) non sarebbe meglio semplicemente compilare ogni metodo per ridurre il sovraccarico di cercare di determinare quali metodi vengono compilati in primo luogo?

+0

@Andrew - Le metriche delle prestazioni di runtime possono dirti se qualcosa deve essere interpretato, così come quanto dovrebbe essere aggressivo (alcune ottimizzazioni JIT richiedono più tempo di altre). – jsight

+0

Solo un'idea (dubito che HotSpot funzioni in questo modo) - puoi analizzare alcune cose (come la lunghezza del metodo) staticamente (generando bytecode) e prendere una decisione rispetto a, e quindi, contrassegna questo metodo con il bit "non compilare" quindi, JIT saprebbe che non dovrebbe compilarlo, quando necessario, invece, ricorrere all'interprete. –

+3

http://java.sun.com/products/hotspot/whitepaper.html - HotSpot può sostituire il codice sul posto, anche mentre il codice è in esecuzione nello stack. Pertanto, un ciclo può iniziare in modalità interpretata, ma completare in modalità compilata JIT una volta completata la ricompilazione. – jsight

3

Sarebbe bello vedere alcune JIT basate su tracce in futuro per dispositivi con poca memoria. Interpreta principalmente, trova i punti caldi e li converte in assembler e li memorizza nella cache. Penso che questo sia ciò che Google fa con il loro JIT Android e Microsoft Research ha un progetto di ricerca in corso per JIT basato su traccia.

Ho trovato un articolo, SPUR: A Trace-Based JIT Compiler for CIL .. Forse un po 'di questo entrerà nello CLR un giorno?

Problemi correlati