2012-04-13 14 views
8

Ho letto e sentito molto su come i compilatori JIT possono effettuare ottimizzazioni che sono impossibili per i compilatori di codici nativi e che queste ottimizzazioni possono dare enormi aumenti di prestazioni.Ottimizzazioni JIT al loro massimo

Quindi mi chiedevo quali sono le ottimizzazioni più importanti che, ad esempio, .NET Framework o JVM fanno che un compilatore nativo non possa fare? Inoltre, in che modo questi danno enormi prestazioni?

Non so se ho formulato questa domanda correttamente, immagino che possa avere un sacco di spiegazioni da dare nei commenti

+0

@TimMedora: il collegamento sembra parlare delle ottimizzazioni eseguite dal compilatore in anticipo C#, non dal compilatore just-in-time CLR. –

risposta

4

posso dare un esempio di uno di ottimizzazione. Supponi di avere una funzione da qualche parte. (Pensi a questo come C-like pseudocodice.)

void function(MyClass x) 
{ 
    x.doSomething(); 
    for (obj in x.getWidgets()) 
     obj.doSomethingElse(); 
} 

Questo è opportunamente vago. Supponiamo, tuttavia, di avere solo una classe concreta nell'intera immagine che eredita da MyClass: MyConcreteClass. In tal caso, la JIT può incorporare doSomething e getWidgets. Se conosce il tipo restituito da getWidgets, allora forse può anche essere in linea doSomethingElse.

Supponendo che MyClass non sia una classe finale/sigillata, un compilatore in anticipo non può inline il suo metodo (non saprebbe quali funzioni inline); per quanto ne sa il compilatore, ci sono cento diverse implementazioni di MyClass.

Tuttavia, un JIT può ottimizzare lo stato corrente dell'immagine dello . È possibile installare un assegno all'inizio di ogni chiamata a function che si assicura che x sia un MyConcreteClass e quindi esegua la versione inline. Se si carica dinamicamente un modulo con un'altra classe concreta ereditata da MyClass, il controllo non riuscirà e il JIT ricompilerà la funzione in modo generico.

Questi sono gli unici tipi di ottimizzazioni a disposizione compilatori JIT che non sono disponibili per ahead-of-time compilatori: ottimizzazioni che fanno uso di informazioni sullo stato dinamico del programma e ricompilare il programma di conseguenza.

Si noti che alcuni compilatori in anticipo sono in grado di eseguire trucchi tipicamente attribuiti ai compilatori JIT. Ad esempio, l'ottimizzazione interprocedurale (o l'ottimizzazione globale) e l'ottimizzazione guidata dal profilo. GCC e Clang possono usare entrambi questi trucchi, ma la maggior parte delle persone li lascia fuori perché richiede un lavoro extra (umano) per accenderli. I compilatori JIT possono lasciare abilitate queste opzioni senza disturbare gli utenti finali.

Enorme aumento delle prestazioni: Non ho mai sentito parlare di un enorme aumento delle prestazioni in generale dai compilatori JIT. I programmi C e C++ sono ancora veloci senza JIT. E molte persone preferiscono ancora Fortran per il lavoro numerico (a ragione).

Nota: Non sono sicuro della tua terminologia. La maggior parte dei JIT non sono compilatori di codice nativo? Gli altri tipi di compilatore oltre a JIT chiamerei "in anticipo" o AOT, o forse "statico". (E poi c'è la linea incredibilmente confusa tra "compilato" e "interpretato".)

+0

-1 per "Questi sono gli unici tipi di ottimizzazioni ..." I compilatori JIT utilizzano l'ottimizzazione guidata del profilo per migliorare le prestazioni del callsite su percorsi di programma a caldo. (Sia MSFT CLR che Hotspot lo fanno). Questo non è lo "stato" del programma, ma piuttosto la dinamica del programma. I compilatori JIT possono utilizzare le informazioni sulla macchina su cui vengono eseguiti per guidare l'ottimizzazione. MSFT CLR esegue questa operazione e Hotspot esegue questa operazione. Questo non ha nulla a che fare con il programma. I compilatori JIT possono anche utilizzare le informazioni * stato * della macchina su cui vengono eseguite per guidare l'ottimizzazione. –

+0

Non so che le attuali macchine virtuali facciano quell'ultima, ma è certamente possibile. –

+0

@MichaelGraczyk: La ragione per cui ho detto "questi sono gli unici tipi di ottimizzazioni" è perché le ottimizzazioni citate possono essere, e in effetti sono supportate dai compilatori non JIT. GCC * eseguirà l'ottimizzazione basata sui profili. La domanda riguarda solo le ottimizzazioni che i compilatori in anticipo non possono fare. –

1

Javascript è un esempio molto migliore in quanto non è così amichevole verso i compilatori come lo sono JVM o CLR.

I compilatori JIT possono generare rappresentazioni specializzate concrete per le classi Javascript che è difficile per i compilatori statici in quanto le classi possono essere modificate in qualsiasi momento durante l'esecuzione del programma. È inoltre possibile integrare in modo speculativo le funzioni chiamate in base ai tipi effettivi (Dietrich Epp l'ha già spiegato nella sua risposta).

I video allo http://code.google.com/p/v8/ spiegano bene tali ottimizzazioni.