Cosa sono ReservedCodeCacheSize e InitialCodeCacheSize?

Qualcuno può spiegare cosa sono l’opzione JVM ReservedCodeCacheSize e InitialCodeCacheSize ? Specificamente quando / perché dovrei cambiarlo? Come posso decidere qual è la taglia giusta?

Questo è ciò che dicono i documenti:

-XX: ReservedCodeCacheSize = 32m Dimensioni della cache del codice riservato (in byte) – dimensione massima della cache del codice. [Solaris 64-bit, amd64 e -server x86: 2048m; in 1.5.0_06 e precedenti, Solaris 64-bit e and64: 1024m.]

ReservedCodeCacheSize (e InitialCodeCacheSize ) è un’opzione per il compilatore (just-in-time) della macchina virtuale Hotspot Java. Fondamentalmente imposta la dimensione massima per la cache del codice del compilatore.

La cache può diventare piena, il che si traduce in avvisi come i seguenti:

 Java HotSpot(TM) 64-Bit Server VM warning: CodeCache is full. Compiler has been disabled. Java HotSpot(TM) 64-Bit Server VM warning: Try increasing the code cache size using -XX:ReservedCodeCacheSize= Code Cache [0x000000010958f000, 0x000000010c52f000, 0x000000010c58f000) total_blobs=15406 nmethods=14989 adapters=362 free_code_cache=835Kb largest_free_block=449792 

È molto peggiore quando viene seguito l’ Java HotSpot(TM) Client VM warning: Exception java.lang.OutOfMemoryError occurred dispatching signal SIGINT to handler- the VM may need to be forcibly terminated .

Quando impostare questa opzione?

  1. quando si verificano errori del compilatore Hotspot
  2. per ridurre la memoria necessaria a JVM (e quindi a rischiare errori del compilatore JIT)

Normalmente non cambieresti questo valore. Penso che i valori predefiniti siano abbastanza buoni perché questi problemi si verificano solo in rare occasioni (nella mia esperienza).

@jeha risponde a tutto ciò che volevo sapere da questa domanda, a parte il valore a cui impostare i parametri. Poiché non ho scritto il codice che stavo implementando, non avevo molta visibilità sull’impronta di memoria che aveva.

Tuttavia, è ansible utilizzare jconsole per collegarsi al processo java in esecuzione, quindi utilizzare la scheda “Memoria” per scoprire la dimensione della cache del codice. Per completezza, i passaggi sono (ambiente VM Linux, anche se sono sicuro che altri ambienti sono simili):

  1. Accendi jconsole sulla tua macchina
  2. Trova l’ID di processo corretto e allegalo a jconsole (ci vorranno alcuni minuti)
  3. Passa alla scheda “Memoria”
  4. Dall’elenco a discesa “Grafico:”, selezionare “Cache codici” “Pool di memoria” ”
  5. Anche in questo caso, potrebbero essere necessari alcuni istanti per l’aggiornamento dello schermo, quindi dovresti vedere qualcosa come: immagine cache del codice jconsole

    Come puoi vedere, il mio codice cache utilizza circa 49 MB. A questo punto avevo ancora il valore predefinito che la documentazione (e @jeha) dice è di 48 MB. Sicuramente una grande motivazione per me per aumentare l’ambientazione!

    Ben.


    1024 MB di default probabilmente lo stava sovradimensionando, ma 48 MB di default sembra sottovalutarlo …

Quando JVM compila il codice, contiene l’insieme delle istruzioni del linguaggio assembly nella cache del codice. La cache del codice ha una dimensione fissa e una volta riempita, la JVM non è in grado di compilare alcun codice aggiuntivo.

La dimensione massima della cache del codice è impostata tramite -XX: ReservedCodeCacheSize = N flag (dove N è l’impostazione predefinita appena menzionata per il particolare compilatore). La cache del codice è gestita come la maggior parte della memoria nella JVM: esiste una dimensione iniziale (-XX: InitialCodeCacheSize = N). L’allocazione della dimensione della cache del codice inizia con la dimensione iniziale e aumenta con il riempimento della cache. La dimensione iniziale della cache del codice varia in base all’architettura del chip e al compilatore in uso. Il ridimensionamento della cache avviene in background e non influisce in alcun modo sulle prestazioni, pertanto l’impostazione della dimensione di ReservedCodeCacheSize (ovvero l’impostazione della dimensione massima della cache del codice) è generalmente necessaria.

Per impostazione predefinita per il server a 64 bit, la dimensione di Java 7 è di 48 MB (con la compilazione su più livelli di 96 MB). In Java 8 per server a 64 bit la dimensione della memoria è di 240 MB.

– Pinaki

Una buona esperienza di apprendimento dal team di ingegneri di Indeed e sfide affrontate durante la migrazione a jdk 8.

http://engineering.indeedblog.com/blog/2016/09/job-search-web-app-java-8-migration/

Conclusione: Jdk 8 ha bisogno di più cache del codice han JDK 7

La dimensione di codecache predefinita per JRE 8 è di circa 250 MB, circa cinque volte maggiore del valore predefinito di 48 MB per JRE 7. La nostra esperienza è che JRE 8 ha bisogno di quel codecache aggiuntivo. Fino ad ora abbiamo cambiato circa dieci servizi fino a JRE 8 e tutti usano codecache quattro volte più di prima.

da https://blogs.oracle.com/poonam/entry/why_do_i_get_message :

Di seguito sono riportati due problemi noti in jdk7u4 + rispetto allo svuotamento di CodeCache:

  1. Il compilatore potrebbe non essere riavviato anche dopo che il numero di CodeCache si riduce a quasi la metà dopo il stream di emergenza.
  2. Lo svuotamento di emergenza può causare un utilizzo elevato della CPU da parte dei thread del compilatore che porta a un peggioramento delle prestazioni complessivo.

Questo problema di prestazioni e il problema del mancato riavvio del compilatore sono stati risolti in JDK8. Per risolvere questi problemi in JDK7u4 +, possiamo aumentare la dimensione della cache del codice utilizzando l’opzione ReservedCodeCacheSize impostandola su un valore maggiore dell’impronta del codice compilato in modo che CodeCache non diventi mai piena. Un’altra soluzione è disabilitare il CodeCache Flushing usando l’opzione -XX: -UseCodeCacheFlushing JVM.

I problemi sopra citati sono stati risolti in JDK8 e nei suoi aggiornamenti.

In modo che le informazioni potrebbero essere degne di nota per i sistemi che eseguono su JDK 6 (avendo il flushing del codice disabilitato) e 7.