Tecnica o utilità per minimizzare il tempo di “riscaldamento” di Java?

Sto supportando un’applicazione di messaggistica Java che richiede bassa latenza (<300 microsecondi che elaborano ciascun messaggio). Tuttavia, la nostra profilazione mostra che la Sun Java Virtual Machine funziona lentamente all'inizio e accelera dopo i primi 5.000 messaggi o giù di lì. I primi 5000 messaggi hanno una latenza di 1-4 millisecondi. Dopo circa i primi 5.000, i messaggi successivi hanno una latenza di ~ 250 microsecondi, con valori anomali occasionali.

È generalmente inteso che questo è un comportamento tipico per un’applicazione Java. Tuttavia, da un punto di vista aziendale non è accettabile dire al cliente che devono aspettare che la JVM si “scaldi” prima di vedere le prestazioni che richiedono. L’applicazione deve essere “riscaldata” prima che il primo messaggio cliente venga elaborato

JVM è l’aggiornamento Sun 1.6.0 4.

Idee per superare questo problema:

  1. Impostazioni JVM, come -XX: CompileThreshold =
  2. Aggiungi un componente per “riscaldare” l’applicazione all’avvio, ad esempio inviando “messaggi falsi” attraverso l’applicazione.
  3. Carica in modo statico applicazioni e classi JDK all’avvio dell’applicazione, in modo che le classi non vengano caricate dai JAR durante l’elaborazione dei messaggi dei clienti.
  4. Qualche utilità o agente Java che realizza una o entrambe le due idee precedenti, in modo da non dover reinventare la ruota.

NOTA: Ovviamente per questa soluzione sto esaminando tutti i fattori, inclusi il chip arch, il tipo di disco e la configurazione e le impostazioni del SO. Tuttavia, per questa domanda voglio concentrarmi su cosa si può fare per ottimizzare l’applicazione Java e minimizzare il tempo di “riscaldamento”.

“Warm-up” in Java è generalmente su due cose:

(1): caricamento della class Lazy: questo può essere aggirato forzandolo a caricare.

Il modo più semplice per farlo è inviare un messaggio falso. Dovresti essere sicuro che il falso messaggio attiverà tutti gli accessi alle classi. Per esempio, se si invia un messaggio vuoto ma il progrom controllerà se il messaggio è vuoto ed eviterà di fare certe cose, allora questo non funzionerà.

Un altro modo per farlo è forzare l’inizializzazione della class accedendo a quella class all’avvio del programma.

(2): L’ottimizzazione in tempo reale: in fase di esecuzione, Java VM ottimizzerà parte del codice. Questo è il motivo principale per cui c’è un periodo di riscaldamento.

Per ovviare a ciò, puoi inviare una serie di messaggi falsi (ma di aspetto reale) in modo che l’ottimizzazione possa finire prima che l’utente la utilizzi.

Un altro che puoi aiutare a facilitare questo è quello di supportare in linea come usare privato e finale il più ansible. il motivo è che, la VM non ha bisogno di cercare la tabella di ereditarietà per vedere quale metodo per essere effettivamente chiamato.

Spero che questo ti aiuti.

Il tuo problema non è la compilazione della class, ma la compilazione “just in time”.

Prova -XX:CompileThreshold=1

Ciò costringerà Java a compilare tutto la prima volta che lo esegue. Rallenterà un po ‘l’avvio del codice, ma non il codice della macchina virtuale (dal momento che viene compilato quando Java è installato). C’è un bug aperto per consentire a Java di compilare JAR personalizzati in modo simile e salvare il risultato per le esecuzioni successive che ridurrebbe notevolmente questo overhead, ma non c’è alcuna pressione per correggere questo bug in qualunque momento.

Una seconda opzione sarebbe quella di inviare 5’000 messaggi falsi all’app per “riscaldarlo”. Vendi come “assicurandoti che tutto sia impostato correttamente”.

[EDIT] Alcune informazioni di base nelle classi di precompilazione: Condivisione dei dati di class

Si consiglia di provare la versione IBM di Java da qui, è ansible aggiungere più classi al pool condiviso: Panoramica sulla condivisione dei dati di class

[EDIT2] Per rispondere alle preoccupazioni sollevate da kittylyst : È vero che questo riempirà rapidamente la cache del codice con metodi che vengono utilizzati una sola volta. E potrebbe anche rallentare l’intera app.

Se lo si imposta su un valore basso, il tempo di avvio dell’applicazione può diventare terribilmente lento. Questo perché l’ottimizzazione JIT + che esegue il codice compilato è più costoso rispetto all’esecuzione del codice una volta in modalità interpretata.

Il problema principale qui è che il codice è ancora compilato “just in time”. Finché non è ansible eseguire tutti i metodi necessari almeno una volta, l’app eseguirà un “hickup” per alcuni millisecondi ogni volta che incontra qualcosa che non è stato compilato prima.

Ma se hai la RAM, la tua app è piccola o puoi aumentare la dimensione della cache del codice e non ti importa il tempo di avvio lento, puoi provarlo. Generalmente, l’impostazione predefinita è abbastanza buona.

Esegui semplicemente una serie di messaggi non opzionali attraverso il sistema prima che venga aperto per un genuino traffico di clienti. 10k messaggi è il solito numero.

Per le app finanziarie (ad esempio FIX), questo viene spesso fatto inviando ordini (a un prezzo molto lontano dalla chiusura della sera prima, per ogni evenienza) al mercato prima che si apra. Saranno tutti respinti, ma non importa.

Se il protocollo che si sta utilizzando è homebrew, al prossimo aggiornamento delle librerie, aggiungere il supporto esplicito per un tipo di messaggio “WARMUP” o “TEST” o “SANITYCHECK”.

Ovviamente, questo probabilmente non compilerà i percorsi specifici della logica dell’applicazione, ma in un’app di messaggistica decente, la parte che si occupa del traffico di rete sarà quasi sicuramente la parte dominante dello stack, quindi non importa.

Stai usando il client o il server JVM? Prova ad avviare il tuo programma con:

 java -server com.mycompany.MyProgram 

Quando si esegue JVM di Sun in questa modalità, JIT compilerà il codice byte in codice nativo in precedenza; per questo motivo, il programma impiegherà più tempo per avviarsi, ma dopo sarà più veloce.

Riferimento: domande frequenti su Java HotSpot VM

Citazione:

Qual è la differenza tra i sistemi -client e -server?

Questi due sistemi sono binari diversi. Sono essenzialmente due diversi compilatori (JIT) che si interfacciano con lo stesso sistema runtime. Il sistema client è ottimale per le applicazioni che richiedono tempi di avvio rapidi o impronte ridotte, il sistema server è ottimale per le applicazioni in cui le prestazioni complessive sono più importanti. In generale, il sistema client è più adatto per applicazioni interattive come le GUI. Alcune delle altre differenze includono la politica di compilazione, i valori predefiniti dell’heap e la politica di inlining.

Se si esegue la modalità server di Hotspot su hardware contemporaneo (con 2 o più core per CPU) e con l’ultima versione di JDK, è ansible utilizzare l’opzione seguente per velocizzare il riscaldamento:

 -server -XX: + TieredCompilation

Vecchio thread, lo so, ma ho trovato questo in internet:

Una cosa molto interessante è l’influenza dell’opzione-XX: CompileThreshold = 1500 a SUN HotSpot JVM. Il valore predefinito è 10000 per Server VM e 1500 per Client VM. Tuttavia impostarlo su 1500 per Server VM rende più veloce della VM client. Impostarlo su 100 diminuisce le prestazioni. E l’uso dell’opzione-Xcomp (che significa che tutto il codice è compilato prima dell’uso) offre prestazioni ancora più basse, il che è sorprendente.

Ora sai cosa fare.

Sembra che il tuo progetto benefici delle garanzie in tempo reale:

Vedi: Real Time Java