MokaByte Numero 34  - Ottobre  99
 
 HotSpot vs JIT
di 
Mauro Molino
Una semplice compilazione al volo può essere sufficiente per migliorare le prestazioni del programma? 
Ma allora a che serve HotSpot, la nuova e tanto declamata VM introdotta di recente?


 


Continuiamo la panoramica sulla tecnologia HotSpot, quella che dovrebbe una volta per tutte far dormire sonni tranquilli agli sviluppatori Java per quel che riguarda le prestazioni

Introduzione
Non è la prima volta che scriviamo di HotSpot sulle colonne di Moka Byte, e la ragione è più che ovvia: da “Java-dipendenti”, vediamo questo come la panacea a tutti i nostri  mali e, in attesa di avere veramente una Virtual Machine oscenamente performante, ne seguiamo l’evoluzione con costanza e pazienza (hmm…..!!).
Dopo gli articoli precedenti sull’argomento, Giovanni Puliti mi ha chiesto di dare un’occhiata ad un articolo pubblicato su Java Pro di Maggio, autore Paul Tyma, dal titolo: Introduzione a HotSpot, e dopo un’attenta lettura ho trovato alcune considerazioni e alcuni spunti che ritengo molto interessanti . Paul sottolinea il fatto che il progetto HotSpot nasce da anni di studi accademici su interpreti auto-ottimizzanti. In particolare fa riferimento a Self, sviluppato dalla Stanford University, che a runtime controlla quali punti impegnino le maggiori risorse CPU ( gli hot spots appunto), e dopo averne individuato uno lo ottimizza. Da quel momento in poi, la porzione di codice trattata dovrebbe in teoria essere più veloce. Da queste posizioni generali, oltre che da alcune considerazioni specifiche per Java, parte il progetto HotSpot.
Si fa notare come , osservando attentamente la struttura di Java, si possano individuare numerosi punti suscettibili di enormi ottimizzazioni.
 
 
 

HotSpot vs JIT
Ma andando a fondo, Hot Spot cos’è esattamente? In parole semplici possiamo dire che si tratta di un interprete un po’ particolare, in quanto in possesso di un sofisticato motore di ottimizzazione che si occupa di individuare gli hot spots nel codice Java durante l’esecuzione. Detto così verrebbe da pensare che in fondo JIT, in quanto compilatore, sia più efficiente di qualsiasi interprete ottimizzato. Paul fa notare come in realtà JIT abbia una serie di difetti rispetto a HotSpot: intanto un compilatore “Just In Time” deve necessariamente effettuare la compilazione alla partenza del programma, causando un tempo morto iniziale, che per programmi complessi può diventare biblico, mentre un interprete parte immediatamente. Nel caso di Hot Spot, l’ottimizzazione scelta su una porzione di codice può anche essere la compilazione di questo (cioè una JITtizzazione) però avremo, invece che una lunga pausa iniziale, molte piccole pause intermedie, quasi sempre non percettibili. Per di più, l’ottimizzazione effettuata da JIT ha delle limitazioni, in quanto quando si trova davanti a caricamento dinamico di classi o “reflection” costringono JIT ad essere conservativo nella sua ottimizzazione per evitare di generare codice poco stabile. Non basta, JIT non sa quali punti sia conveniente ottimizzare e quali no, quindi effettua una compilazione indiscriminata, che porta via parecchio tempo, quando è ormai assodato che in media è il 20% del codice di un programma a portare via oltre l’80% del tempo di elaborazione. In questo HotSpot presenta numerosi vantaggi, dalla partenza rapida, all’individuazione dei punti critici, effettuando così una ottimizzazione sul processo di ottimizzazione. 
 
 
 

Considerazioni sull’ottimizzazione di Java
Nel suo articolo, Paul pone alcune questioni di non poco conto. Giustamente sostiene che il caricamento dinamico (dynamic loading) e il meccanismo di “reflection” rappresentano un punto di forza indiscutibile di Java, permettendo di costruire del codice altamente riutilizzabile e in qualche modo “intelligente”. Per contro, queste due possibilità diventano un incubo per l’ottimizzazione. L’esempio portato è semplice ma molto chiaro: nel caso della porzione di pseudo-codice seguente:

 x=false;
 if (x) do this();
è facilmente comprensibile che la seconda riga di codice non sarà mai eseguita, e un profiler sarà in grado di ottimizzare il codice eliminandone le parti inutili. Questo è però valido solo nel caso in cui x sia una variabile locale, altrimenti c’è la possibilità che qualche thread esterno possa modificare la variabile rendendola vera e consentendo così l’esecuzione della porzione di codice successiva. Quindi possiamo dire che sarebbe possibile eliminare lo “statement” in esame quando:
  1. siamo sicuri che la nostra applicazione sia  a Thread singolo
  2. siamo sicuri che il metodo che contiene le 2 righe di codice non viene mai chiamato ( controllando quindi tutte le classi dell’applicazione) 
  3. siamo sicuri che da nessuna parte viene fatta l’assegnazione A.x= qualcosa, dove A sia la classe contenente il nostro codice.
Come si vede, la mole di lavoro che un JIT deve compiere per poter stabilire se sia legittimo eliminare la riga  di “if”  è enorme, e comunque richiede che si abbiano a priori tutta una serie di informazioni sulla classe in esame. E qui viene il bello; abbiamo prima sottolineato quanto sia potente il meccanismo di caricamento dinamico delle classi in Java, ebbene, questa funzionalità impedisce che un compilatore possa in anticipo avere quelle informazioni necessarie per l’ottimizzazione. HotSpot risolve questi problemi perché non richiede conoscenze a priori delle classi in esame, infatti la sua analisi di ottimizzazione si basa su dati che ottiene a run-time, quindi analizza una classe che sia già stata caricata e per la quale possa quindi accedere a tutte le informazioni del caso.
Le due tecnologie analizzate, cioè l’ottimizzazione statica a priori e l’ottimizzazione adattiva rappresentano due approcci  totalmente differenti al processo di “profiling” del codice. Per di più, ladove enga richiesto, HotSpot è in grado di de-ottimizzare parti di codici, come nel caso di un metodo al quale sia stato applicato l’ ”in-lining”, e che a run-time subisca un “overriding”. In questo caso HotSpot è in grado di de-ottimizzare il codice evitando pericolosi effetti collaterali.
 
 
 

Garbage Collector
Nel prosieguo del suo articolo Paul passa in esame alcune caratteristiche del garbage collector di HotSpot, sottolineando come secondo lui sia il più avanzato in circolazione. Il GC della VM Sun classica è di tipo generazionale, quello di HotSpot è: generazionale, incrementale, esatto. Generazionale perché gli oggetti vengono categorizzati in base alla loro età, non cronologica, ma espressa in numero di passaggi di GC. L’algoritmo utilizzato è per alcuni versi modulare, nel senso che è possibile sostituirlo senza problemi nel momento in cui se ne abbia a disposizione uno migliore.Il GC di HotSpot è incrementale. Cioè? In generale durante l’esecuzione di una applicazione, i processi in corso si bloccano e passano il controllo al GC, che svolge il suo lavoro e poi ricede il controllo. Questo processo è responsabile dei momenti di “guru meditation” ai quali talvolta si assiste durante l’esecuzione di un programma Java. Il GC di HotSpot invece, svolge il proprio lavoro un po’ alla volta, evitando lunghe pause applicative. Questo deve essere costato molto in termini di sviluppo del GC, ma gli effetti benefici sono più che evidenti.
 
 
 

Prestazioni
Questo è un argomento che abbiamo già trattato più volte, ma l’evoluzione di HotSpot di recente ha avuto delle impennate non indifferenti, per cui vale la pena soffermarvisi ancora una volta. Nella primissima versione di HotSpot, Sun stessa sottolineava come il profiler fosse consigliato soprattutto per piattaforme server e, aggiungo io, quel soprattutto significava in realtà  “quasi esclusivamente”. Il processo di ottimizzazione partiva dopo un certo “rodaggio” dell’applicazione, e cominciava a dare qualche risultato dopo diversi minuti di utilizzo massiccio, rendendolo così praticamente inutilizzabile per programmi client. Nella versione integrata nel jdk1.3 però si parla di HotSpot versione “client”, e in effetti dalle prove effettuate i miglioramenti sono abbastanza percettibili ( vedi articolo del mese scorso sul jdk1.3). E’ subito evidente l’assenza delle fastidiose pause durante le normali elaborazioni di programma, e questo è riconducibile al discorso fatto prima sul nuovo algoritmo di garbage collector utilizzato, e gli effetti dell’ottimizzazione sono percettibili dopo pochi secondi di utilizzo del programma, segno che i metodi di ottimizzazione utilizzati sono stati sicuramente migliorati per rendere il profiler utilizzabile a livello client. Peraltro mi preme sottolineare una cosa che ritengo abbastanza importante: Hot Spot può sicuramente fare salti da gigante per portare Java a prestazioni eccellenti, ma non nascondiamoci dietro semplici problemi di compilazione per giustificare alcune carenze di performance. E’ sicuramente vero che tutta la piattaforma Java sia suscettibile di significativi miglioramenti, e questo è evidente dal fatto che ad ogni nuova release, con la correzione di alcuni bugs, le prestazioni ne risentono positivamente. Ad esempi, nel Jdk1.3 sono apprezzabili alcuni miglioramenti prestazionali delle Swing, indipendentemente da HotSpot. Il garbage collector, per quanto molto più affidabile di prima è ben lungi dal potersi considerare pienamente ottimizzato e qualche ritocco è ancora necessario per le classi di input/output. Abbiamo visto come , la reimplementazione delle classi matematiche abbia portato ad un incredibile aumento di velocità di calcolo. E poi non dimentichiamo quel 40% di prestazioni dovuto alla scrittura di buon codice, in barba a qualsiasi profiler………………..
 
 
 

Conclusioni 
Forse Hot Spot ha raggiunto una certa maturità. Ci sono ancora buoni margini di miglioramento, ma come ho già scritto, sono tanti e tali i punti di intervento sulla piattaforma complessiva Java, che potrebbero apportare benefici, che probabilmente alla fine l’importanza di HotSpot nel processo di evoluzione di Java potrebbe essere ridimensionata all’interno di canoni di normalità.

 
 
 

MokaByte rivista web su Java

MokaByte ricerca nuovi collaboratori
Chi volesse mettersi in contatto con noi può farlo scrivendo a mokainfo@mokabyte.it