Attualmente sto valutando il garbage collector G1 e come si comporta per la nostra applicazione. Guardando il gc-log, ho notato un sacco di collezioni hanno molto lunghe "Scan RS" fasi:Perché Java G1 gc trascorre così tanto tempo nella scansione di RS?
7968.869: [GC pause (mixed), 10.27831700 secs]
[Parallel Time: 10080.8 ms]
(...)
[Scan RS (ms): 4030.4 4034.1 4032.0 4032.0
Avg: 4032.1, Min: 4030.4, Max: 4034.1, Diff: 3.7]
[Object Copy (ms): 6038.5 6033.3 6036.7 6037.1
Avg: 6036.4, Min: 6033.3, Max: 6038.5, Diff: 5.2]
(...)
[Eden: 19680M(19680M)->0B(20512M) Survivors: 2688M->2624M Heap:
75331M(111904M)->51633M(115744M)]
[Times: user=40.49 sys=0.02, real=10.28 secs]
Tutti i rimosse log-righe voci mostrano tempi di esecuzione in ms a una cifra.
Penso che la maggior parte del tempo dovrebbe essere speso per la copia, giusto? Quale potrebbe essere la ragione per cui Scan RS impiega così tanto tempo? Qualche idea su come modificare le impostazioni G1? La JVM è stato avviato con
-Xms40960M -Xmx128G -XX:+UseG1GC -verbose:gc -XX:+PrintGCDetails -Xloggc:gc.log
Edit: Ah, dimenticavo ... sto usando Java 7u25
Aggiornamento: ho notato altre due cose strane:
16187.740: [GC concurrent-mark-start]
16203.934: [GC pause (young), 2.89871800 secs]
(...)
16218.455: [GC pause (young), 4.61375100 secs]
(...)
16237.441: [GC pause (young), 4.46131800 secs]
(...)
16257.785: [GC pause (young), 4.73922600 secs]
(...)
16275.417: [GC pause (young), 3.87863400 secs]
(...)
16291.505: [GC pause (young), 3.72626400 secs]
(...)
16307.824: [GC pause (young), 3.72921700 secs]
(...)
16325.851: [GC pause (young), 3.91060700 secs]
(...)
16354.600: [GC pause (young), 5.61306000 secs]
(...)
16393.069: [GC pause (young), 17.50453200 secs]
(...)
16414.590: [GC concurrent-mark-end, 226.8497670 sec]
L'esecuzione concomitante del GC prosegue mentre vengono eseguite le esecuzioni parallele. Non sono sicuro che sia intenzionale, ma mi sembra abbastanza sbagliato. Certo, questo è un esempio estremo, ma vedo questo comportamento in tutto il mio registro.
Un'altra cosa è che il mio processo JVM è cresciuto a 160g. Considerando un heap di 128 g, si tratta di un overhead piuttosto ampio. È prevedibile o G1 perde memoria? Qualche idea su come scoprirlo?
PS: Io non sono davvero sicuro se devo aver fatto nuove domande per gli aggiornamenti ... se qualcuno di voi pensa che ciò sia utile, mi dica;)
Update 2: Immagino che il G1 possa davvero perdere memoria: http://printfdebugger.tumblr.com/post/19142660766/how-i-learned-to-love-cms-and-had-my-heart-broken-by-g1 Dato che per ora questo è un rompicapo, non ho intenzione di passare più tempo a giocare con questo. Le cose che non ho ancora provato sono la configurazione della dimensione della regione (-XX: G1HeapRegionSize) e l'occupazione dell'heap (-XX: InitiatingHeapOccupancyPercent).
160 GB? Wow! Su cosa stai lavorando? –
Pianificazione/reporting in memoria per catene di approvvigionamento globali. Non dire che l'impronta non può essere ridotta, ma sicuramente può essere un sacco di dati per i grandi clienti. – JohannesR
Se hai molta memoria, ha senso utilizzarla. È fantastico che JVM sia in grado di gestirli (anche se vedo i tuoi problemi). –