2010-01-02 14 views
94

L'implementazione canonica JVM di Sun applica un'ottimizzazione piuttosto sofisticata al bytecode per ottenere velocità di esecuzione near-native dopo che il codice è stato eseguito alcune volte.Perché il codice JIT della cache JIT non è compilato?

La domanda è, perché questo codice compilato non è memorizzato su disco per l'utilizzo durante gli usi successivi della stessa funzione/classe?

Allo stato attuale, ogni volta che viene eseguito un programma, il compilatore JIT riprende in modo nuovo, anziché utilizzare una versione precompilata del codice. L'aggiunta di questa funzione non aggiungerebbe una spinta significativa al tempo di esecuzione iniziale del programma, quando il bytecode viene essenzialmente interpretato?

+5

+1 buona domanda, che – skaffman

+4

Una discussione che illustra questo problema: http://www.javalobby.org/forums/thread.jspa?threadID=15812 – miku

+2

Ma una domanda improbabile per attirare una risposta definitiva. – bmargulies

risposta

25

Senza ricorrere al cut'n'paste del collegamento che @MYYN ha pubblicato, ho il sospetto che ciò sia dovuto al fatto che le ottimizzazioni eseguite dalla JVM non sono statiche, ma piuttosto dinamiche, basate sui pattern di dati e sui pattern di codice. È probabile che questi modelli di dati cambieranno durante la vita dell'applicazione, rendendo le ottimizzazioni memorizzate nella cache meno che ottimali.

Quindi sarebbe necessario un meccanismo per stabilire se le ottimizzazioni salvate fossero ancora ottimali, a quel punto si potrebbe anche solo ottimizzare nuovamente al volo.

+4

... o potresti semplicemente offrire la persistenza come * opzione *, come fa la JVM di Oracle - potenziare * i programmatori avanzati * per ottimizzare le prestazioni dell'applicazione quando e dove solo ** sanno ** i modelli sono ** non ** cambiando, sotto la loro responsabilità. Perchè no?! –

+2

Perché probabilmente non ne vale la pena. Se né SUN, IBM né BEA ritengono che valga la pena per le loro prestazioni JVM, ci sarà una buona ragione per farlo. Forse la loro ottimizzazione RT è più veloce di quella di Oracle, motivo per cui Oracle la memorizza nella cache. – skaffman

+8

Perché non utilizzare le ottimizzazioni memorizzate come punto di partenza, per utilizzare quanto appreso nelle sessioni precedenti? Da lì JIT potrebbe funzionare come al solito un re-ottimizzare le cose. Allo spegnimento, quel codice potrebbe essere persistente e essere utilizzato nella prossima esecuzione come un nuovo punto di partenza. – Puce

24

Oracle's JVM è infatti documentato a farlo - citando Oracle,

il compilatore può usufruire del modello di risoluzione classe di Oracle JVM per opzionalmente persistono compilati Java metodi attraverso chiamate al database, sessioni, o le istanze. Tale persistenza di evita il sovraccarico delle ricompense non necessarie durante le sessioni , quando è noto che semanticamente il codice Java non è stato modificato.

Non so perché tutte le sofisticate implementazioni VM non offrono opzioni simili.

+7

Perché altre JVM sofisticate non lo fanno avere a disposizione un ottimo RDBMS aziendale per memorizzare le cose :) – skaffman

+0

Wow! ciò significa che le Compilation sono memorizzate nella cache a volte. Questa è una buona notizia! –

+0

Anche IBM J9 è documentato per farlo. – user314104

1

Non conosco i motivi reali, non essendo in alcun modo coinvolti nella realizzazione JVM, ma mi viene in mente alcuni tra quelli plausibili:

  • L'idea di Java è quello di essere un write-volta- linguaggio run-anywhere, e mettere le cose precompilate nel file di classe è un tipo di violazione (solo "tipo di" perché ovviamente il codice byte effettivo sarebbe ancora lì)
  • Aumenterebbe le dimensioni del file di classe perché avresti lo stesso codice esiste più volte, specialmente se si esegue lo stesso programma in più JVM diverse (cosa non molto rara, se si considerano versioni diverse da JV differenti Ms, che devi davvero fare)
  • Gli stessi file di classe potrebbero non essere scrivibili (anche se sarebbe abbastanza facile controllarli)
  • Le ottimizzazioni JVM sono parzialmente basate su informazioni di runtime e su altre esecuzioni potrebbero non essere altrettanto applicabili (anche se dovrebbero comunque fornire qualche beneficio)

Ma credo davvero, e come potete vedere, non credo che nessuno dei miei motivi sia un vero ostacolo. Immagino che Sun non consideri questo supporto come una priorità, e forse il mio primo motivo è vicino alla verità, poiché farlo abitualmente potrebbe anche indurre le persone a pensare che i file di classe Java abbiano davvero bisogno di una versione separata per ogni VM invece di essere piattaforme.

Il mio modo preferito sarebbe in realtà di avere un traduttore separato da bytecode a nativo che potreste usare per fare qualcosa del genere in modo esplicito, creando file di classe che sono costruiti esplicitamente per una VM specifica, con possibilmente il bytecode originale in in modo da poter essere eseguiti con diverse VM. Ma questo probabilmente deriva dalla mia esperienza: ho fatto principalmente Java ME, dove fa davvero male che il compilatore Java non sia più intelligente sulla compilazione.

+1

c'è un punto nel file di classe per tali cose, infatti quello era l'intento originale (memorizzare il codice JIT come attributo nel file class). – TofuBeer

+0

@TofuBeer: grazie per la conferma. Sospettavo che potesse essere il caso (è quello che avrei fatto), ma non ero sicuro. Modificato per rimuovere ciò come possibile motivo. – JaakkoK

+0

Penso che tu abbia colpito il chiodo sulla testa con il tuo ultimo punto elenco. Gli altri potrebbero essere risolti, ma l'ultima parte è, credo, il motivo principale per cui il codice JITed non è persistente. –

5

Excelsior JET ha un compilatore JIT caching a partire dalla versione 2.0, rilasciato nel 2001. Inoltre, il suo compilatore AOT può ricompilare la cache in un/oggetto condiviso singola DLL utilizzando tutte le ottimizzazioni.

+3

Sì, ma la domanda riguardava la JVM canonica, ovvero la JVM di Sun. Sono ben consapevole del fatto che ci sono diversi compilatori AOT per Java e altre JVM di memorizzazione nella cache. –

10

Un aggiornato per le risposte esistenti - Java 8 ha una PEC dedicato alla soluzione di questo:

=>JEP 145: Cache Compiled Code. New link.

A un livello molto alto, il suo dichiarato obiettivo è :

salvare e riutilizzare compilato codice nativo da esecuzioni precedenti, al fine di migliorare il tempo di avvio di grandi applicazioni Java.

Spero che questo aiuti.

+3

La funzione non è passata a [la versione finale] (http://openjdk.java.net/projects/jdk8/features). – assylias

+2

Collegamento interrotto. --- –

+1

Vedere anche (http://stackoverflow.com/questions/39394819) – MRalwasser