Home Arrow Icon Knowledge base Arrow Icon Global Arrow Icon Come posso configurare i parametri JVM per ridurre al minimo le pause della raccolta dei rifiuti


Come posso configurare i parametri JVM per ridurre al minimo le pause della raccolta dei rifiuti


Per configurare i parametri JVM per minimizzare le pause della Garbage Collection (GC), è importante comprendere le operazioni fondamentali di diversi collezionisti di immondizia e i meccanismi di accordatura disponibili nel JVM. Il processo di configurazione prevede la selezione di un algoritmo di raccolta della spazzatura appropriato, la messa a punto delle dimensioni del heap, la configurazione di obiettivi di tempo di pausa, i parametri di threading e l'ottimizzazione delle regioni di memoria. Di seguito è riportata una sintesi dettagliata della messa a punto JVM per ridurre al minimo le pause GC in base a fonti autorevoli e migliori pratiche:

Scegliere il collettore di immondizia giusto

JVM offre più algoritmi di raccolta dei rifiuti, ciascuno con caratteristiche diverse per quanto riguarda il throughput, i tempi di pausa e l'utilizzo delle risorse:

- Serial GC: utilizza un singolo thread per GC. Ferma tutti i thread dell'applicazione durante la raccolta, con conseguenti pause lunghe. In genere non è adatto per ridurre al minimo le pause in applicazioni più grandi.
- GC parallelo: utilizza più thread per eseguire la raccolta della spazzatura, riducendo i tempi di pausa rispetto al GC seriale sfruttando più core CPU. È orientato alla throughput ma fa comunque una pausa i thread dell'applicazione durante GC.
- CONCURNENTE MARK-SWEEP (CMS) GC: svolge gran parte del lavoro di raccolta della spazzatura contemporaneamente all'applicazione, riducendo significativamente i tempi di pausa facendo solo brevemente l'applicazione in fasi GC specifiche. È adatto per applicazioni a bassa latenza.
- Garbage First (G1) GC: divide il mucchio in regioni e si concentra sulla raccolta di regioni con la maggior parte della spazzatura. Mira a fornire tempi di pausa prevedibili e un buon rendimento miscelando fasi simultanee e parallele. È spesso l'impostazione predefinita nelle moderne versioni JVM.
- Shenandoah e ZGC: questi collezionisti a bassa latenza svolgono tutto o la maggior parte del lavoro GC contemporaneamente, mirando a pause molto brevi o quasi impercettibili, adatti a grandi cumuli e applicazioni altamente reattive.

La scelta del collettore giusto dipende dai requisiti dell'applicazione come il tempo di pausa tollerato massimo, la dimensione del heap e le caratteristiche del carico di lavoro.

Configurazione della dimensione

heap

La dimensione del heap ha un impatto diretto sulla frequenza GC e sulla pausa:

-Imposta dimensione iniziale e massima di heap uguale: usando `-xms` e` -xmx` con lo stesso valore evita il ridimensionamento del heap, che può introdurre pause durante il runtime.
- dimensioni del mucchio adeguate: un mucchio sotto-allocazione provoca collezioni frequenti, aumentando le pause. Tuttavia, l'eccessiva allocazione porta a cicli GC più lunghi. Trova un saldo in base alle esigenze di memoria dell'applicazione.
- Monitorare i registri GC e le metriche di utilizzo dell'heap per sintonizzare in modo appropriato la dimensione del heap.

Controllo del tempo di pausa GC

JVM fornisce parametri per fissare obiettivi per i tempi di pausa GC massimi:

- `-xx: maxGCPauseMillis =`: imposta un tempo di pausa massimo target in millisecondi per il collettore per cercare di incontrarsi. Sebbene non garantito, il JVM tenta di regolare la throughput e il lavoro GC per evitare di superare questo tempo di pausa.
- Utilizzare questo parametro con G1 GC o altri collezionisti che supportano gli obiettivi di pausa per guidare il JVM nel bilanciamento della throughput e della latenza.

threading e parallelismo

Sfruttare più thread durante la collezione di immondizia riduce le durate di pausa:

- `-xx: parallelgcthreads =`: imposta il numero di thread utilizzati durante le fasi parallele di GC. Più thread possono ridurre il tempo di pausa ma possono anche aumentare l'utilizzo della CPU.
- `-xx: ConcGCThreads =`: per collezionisti simultanei come CMS e G1, imposta il numero di thread che eseguono fasi simultanee.
- Il conteggio ottimale dei thread dovrebbe allinearsi con il numero di core della CPU disponibili e il carico di lavoro; I thread di iscrizione eccessiva possono degradare le prestazioni.

Tuning di piccole e vecchie dimensioni di generazione

Il heap è in genere diviso in generazioni giovani e vecchi. Sintonizzare le loro dimensioni influisce sul comportamento GC:

- Dimensione delle giovani generazioni: la più grande generazione di giovani generazioni riduce la frequenza di GC minori ma aumenta i tempi di pausa GC minori. Regola in base al tasso di allocazione degli oggetti.
- Dimensione di vecchia generazione: influenza la frequenza con cui i GC principali/completi funzionano e la loro durata.
- G1 GC divide il heap in molte regioni equamente di dimensioni e gestisce la dimensione in modo dinamico, ma consente le soglie di iniziazione di messa a punto con parametri come `-xx: InitiatingHeapCupancyPercent`.

parametri specifici del collettore di garbage

Per G1 GC, comunemente usato nei JVM moderni:
- `-xx:+useg1gc`: abilita g1 gc.
- `-xx: maxGCPAuseMillis =`: pausa Time Target.
- `-xx: InitiatingHeapCupancyPercent =`: inizia la marcatura simultanea quando il mucchio raggiunge questa occupazione.
- `-xx:+usestringdeduplication`: riduce l'impronta di memoria deduplicando le stringhe.
- Evita di impostare esplicitamente la dimensione della generazione delle giovani, in quanto può interferire con gli obiettivi di pausa di G1.

Per CMS GC:
- `-xx:+useconcmarksweepgc`: abilita CMS.
-Sortoscarsi la messa a fuoco sulla riduzione delle pause di arresto globale del mondo regolando la soglia di iniziazione e il conteggio dei fili.

Per GC parallelo (orientato alla throughput):
-`-xx:+usaparallelgc` e` -xx:+usaparalleloldgc`: abilita GC parallelo per giovani e vecchie generazioni.
- Sintonizza il numero di thread GC con `-xx: parallelgcthreads`.

riducendo il tasso di allocazione degli oggetti

Ridurre la velocità con cui vengono creati nuovi oggetti riduce la pressione GC:

- Profilo e ottimizza il codice per ridurre al minimo la creazione di oggetti non necessaria.
- Usa il pooling e il riutilizzo degli oggetti quando possibile.
- Regola i parametri JVM per regolare le regioni di memoria interna per modelli di allocazione di oggetti migliori.

Evita le chiamate GC esplicite

- Disabilita le chiamate GC esplicite dal codice dell'applicazione o dagli strumenti esterni che possono attivare pause GC complete utilizzando `-xx:+DisableExplicitGC`.

monitoraggio e registrazione

Per capire e sintonizzare il comportamento GC, abilitare la registrazione GC dettagliata:

- Usa `-xlog: GC*` in JVMS Supporting Unified Logging (Java 9+).
-In JVMS più vecchio, usa `-xx:+printgcdetails -xx:+printgcdatestamps -xloggc:`.

Analizzare i registri per identificare le cause e sintonizzarsi di conseguenza.

Raccomandazioni generali

- Inizia a sintonizzare con una lavagna pulita rimuovendo gli argomenti JVM obsoleti.
- Test cambiamenti in un ambiente simile alla produzione.
- Utilizzare strumenti come il registratore di volo Java, VisualVM o i profili commerciali per raccogliere dati di utilizzo GC e di memoria.
- Iterare i passaggi di accordatura basati sui tempi di pausa GC osservati, il throughput e la reattività dell'applicazione.

In sintesi, minimizzare le pause della raccolta della spazzatura JVM comporta la selezione del collettore di immondizia appropriato (preferibilmente G1, ZGC o Shenandoah per i requisiti di pausa a bassa pausa), dimensionando correttamente il heap e le generazioni, impostando gli obiettivi di tempo della pausa, tune di tuni thread di concorrenza, minimizzando il tasso di allocazione degli oggetti, disabilitando il GC esplicito e il monitoraggio attento. Le specifiche dipenderanno dal carico di lavoro dell'applicazione, dalla dimensione del heap, dalla versione JVM e dalle caratteristiche hardware. Le regolazioni devono essere apportate in modo incrementale e validate con strumenti di monitoraggio e registri GC dettagliati per raggiungere il bilancio desiderato del throughput e del tempo di pausa.

Questo approccio garantisce che la raccolta della spazzatura di JVM funzioni in modo efficiente con interruzioni minime delle prestazioni dell'applicazione.