Mi capita spesso di sentir parlare di compilatori JIT (Just In Time) e Optimizer (ottimizzatori) e mi accorgo che spesso i due sono trattati allo stesso modo, seppur siano differenti. La differenza maggiormente evidente è che un JIT compiler compila il corpo di un metodo in codice nativo al primo accesso al metodo stesso, mentre un optimizer (ri)compila il metodo in codice nativo quando lo ritiente opportuno (ovvero quando si può verificare una vera e propria ottimizzazione).
Per comprendere meglio, si consideri il generico metodo foo() che viene richiamato dall'applicazione. Il JIT compiler compilerà foo() in codice nativo al suo primo accesso, mentre un optimizer lo ricompilerà solo quando il numero di accessi al metodo sarà tale da far migliorare le prestazioni. In altre parole, l'optimizer analizza il codice in esecuzione e decide se, in base al numero di chiamate di foo() questo sia un metodo molto utilizzato (metodo hot) e quindi possa necessitare di ottimizzazioni (in particolare una ricompilazione in codice macchina) per le successive (si pensa frequenti) invocazioni.
Chiaramente entrambi i compilatori possono generare differenti ottimizzazioni, quali rimozione di codice inusato (dead code), srotolamento dei cicli, copy propagation, ecc. Ma la differenza sostanziale fra i due tipi di compilatori è nella decisione che viene presa circa la compilazione di un metodo in codice nativo.
Chiaramente si nota poi come un compilatore optimizer debba avere anche un supporto adattativo, ossia debba essere in grado di comprendere quando è ora di compilare un metodo. Per fare questo, occorre un qualche meccanismo di memorizzazione delle statistiche run-time di un sistema JVM.
Nessun commento:
Posta un commento