Domanda

Il mio professore ha fatto un benchmark informale su un piccolo programma e i tempi di Java erano:1,7 secondi per la prima corsa e 0,8 secondi per le corse successive.

  • Ciò è dovuto interamente al caricamento dell'ambiente runtime nell'ambiente operativo?

    O

  • È influenzato dall'ottimizzazione del codice da parte di Java e dalla memorizzazione dei risultati di tali ottimizzazioni (mi spiace, non conosco il termine tecnico per questo)?

È stato utile?

Soluzione

Sono d'accordo che la differenza di prestazioni vista dal poster è molto probabilmente causata dalla latenza del disco che porta JRE in memoria.Il compilatore Just In Time (JIT) non avrebbe alcun impatto sulle prestazioni di una piccola applicazione.

Java 1.6u10 (http://download.java.net/jdk6/) tocca i JAR di runtime in un processo in background (anche se Java non è in esecuzione) per mantenere i dati nella cache del disco.Ciò riduce significativamente i tempi di avvio (il che è un enorme vantaggio per le app desktop, ma probabilmente di valore marginale per le app lato server).

Nelle applicazioni di grandi dimensioni e di lunga durata, il JIT fa una grande differenza nel tempo, ma il tempo necessario al JIT per accumulare statistiche sufficienti per attivarsi e ottimizzare (5-10 secondi) è molto, molto breve rispetto alla vita complessiva dell'applicazione (la maggior parte viene eseguita per mesi e mesi).Sebbene l'archiviazione e il ripristino dei risultati JIT sia un esercizio accademico interessante, il miglioramento pratico non è molto ampio (motivo per cui il team JIT si è concentrato maggiormente su aspetti come le strategie GC per ridurre al minimo gli errori nella cache di memoria, ecc...).

La precompilazione delle classi runtime aiuta parecchio le applicazioni desktop (così come il già citato precaricamento della cache del disco 6u10).

Altri suggerimenti

Ok, ho ritrovato dove l'ho letto.Tutto questo è tratto da "Learning Java" (O'Reilly 2005):

Il problema con una compilazione JIT tradizionale è che l'ottimizzazione del codice richiede tempo.Pertanto un compilatore JIT può produrre risultati decenti ma potrebbe subire una latenza significativa all'avvio dell'applicazione.Questo generalmente non è un problema per le applicazioni lato server di lunga durata, ma è un problema serio per il software e le applicazioni lato client eseguiti su dispositivi più piccoli con capacità limitate.Per risolvere questo problema, la tecnologia del compilatore Sun, chiamata HotSpot, utilizza un trucco chiamato compilazione adattiva.Se si guarda a cosa fanno effettivamente i programmi, si scopre che passano quasi tutto il loro tempo eseguendo ripetutamente una parte relativamente piccola del codice.La porzione di codice eseguita ripetutamente può rappresentare solo una piccola frazione dell'intero programma, ma il suo comportamento determina le prestazioni complessive del programma.La compilazione adattiva consente inoltre al runtime Java di sfruttare nuovi tipi di ottimizzazioni che semplicemente non possono essere eseguite in un linguaggio compilato staticamente, da qui l'affermazione che in alcuni casi il codice Java può essere eseguito più velocemente di C/C++.

Per sfruttare questo fatto, HotSpot inizia come un normale interprete di bytecode Java, ma con una differenza:misura (profila) il codice mentre è in esecuzione per vedere quali parti vengono eseguite ripetutamente.Una volta individuato quali parti del codice sono cruciali per le prestazioni, HotSpot compila tali sezioni in un codice macchina nativo ottimale.Poiché compila solo una piccola porzione del programma in codice macchina, può permettersi di dedicare il tempo necessario all'ottimizzazione di tali porzioni.Potrebbe non essere necessario compilare il resto del programma, ma solo interpretarlo, risparmiando memoria e tempo.In effetti, la Java VM predefinita di Sun può essere eseguita in due modalità:client e server, che gli dicono se enfatizzare tempi di avvio rapidi e conservazione della memoria o prestazioni al massimo.

Una domanda naturale da porsi a questo punto è: perché buttare via tutte queste utili informazioni di profilazione ogni volta che un'applicazione si chiude?Ebbene, Sun ha parzialmente affrontato questo argomento con il rilascio di Java 5.0 attraverso l'uso di classi condivise di sola lettura archiviate in modo persistente in una forma ottimizzata.Ciò riduce significativamente sia il tempo di avvio che il sovraccarico derivante dall'esecuzione di molte applicazioni Java su una determinata macchina.La tecnologia per farlo è complessa, ma l’idea è semplice:ottimizza le parti del programma che devono essere veloci e non preoccuparti del resto.

Mi chiedo quanta strada abbia fatto Sun con Java 5.0.

Non sono a conoscenza di alcuna macchina virtuale ampiamente utilizzata che salvi i dati statistici sull'utilizzo tra le invocazioni del programma, ma è certamente una possibilità interessante per la ricerca futura.

Ciò che vedi è quasi certamente dovuto alla memorizzazione nella cache del disco.

Sono d'accordo che è probabilmente il risultato della memorizzazione nella cache del disco.

Per tua informazione, IBM Java 6 VM contiene un compilatore anticipato (AOT).Il codice non è ottimizzato come quello che produrrebbe JIT, ma è archiviato su VM, credo in una sorta di memoria condivisa persistente.Il suo vantaggio principale è migliorare le prestazioni dell'avvio.Per impostazione predefinita, la VM IBM esegue JIT con un metodo dopo che è stata chiamata 1000 volte.Se sa che un metodo verrà chiamato 1000 volte solo durante l'avvio della VM (si pensi a un metodo comunemente usato come java.lang.String.equals(...) ), quindi è utile memorizzarlo nella cache AOT in modo da non dover mai perdere tempo a compilare in fase di runtime.

Dovresti descrivere come è stato eseguito il tuo Benchmark.Soprattutto a quel punto inizi a misurare il tempo.

Se includi il tempo di avvio della JVM (che è utile per il benchmarking dell'esperienza utente ma non così utile per ottimizzare il codice Java), potrebbe trattarsi di un effetto di memorizzazione nella cache del file system o può essere causato da una funzionalità chiamata "Condivisione dati classe Java":

Per il sole:

http://java.sun.com/j2se/1.5.0/docs/guide/vm/class-data-sharing.html

Questa è un'opzione in cui la JVM salva un'immagine preparata delle classi runtime in un file, per consentire un caricamento (e una condivisione) più rapido di quelle all'avvio successivo.Puoi controllarlo con -Xshare:on o -Xshare:off con una Sun JVM.Il valore predefinito è -Xshare:auto che caricherà l'immagine delle classi condivise se presente e, se non presente, la scriverà al primo avvio se la directory è in scrittura.

Con IBM Java 5 questo è tra l'altro ancora più potente:

http://www.ibm.com/developerworks/java/library/j-ibmjava4/

Non conosco nessuna JVM tradizionale che stia salvando le statistiche JIT.

Java JVM (in realtà potrebbe cambiare da diverse implementazioni della JVM) al primo avvio interpreterà il codice byte.Una volta rilevato che il codice verrà eseguito un numero sufficiente di volte, lo eseguirà tramite JIT nel linguaggio macchina nativo in modo che venga eseguito più velocemente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top