Questo è uno stack di memoria (che funge da cache) costituito da nient'altro che una ConcurrentHashMap (CHM) statica.Memoria completamente utilizzata da Java ConcurrentHashMap (in Tomcat)
Tutti i dati delle richieste HTTP in arrivo sono archiviati in questa ConcurrentHashMap. E c'è un processo di scheduling asincrono che prende i dati dalla stessa ConcurrentHashMap e rimuove il valore key.value dopo averli memorizzati nel Database.
Questo sistema funziona bene e liscia, ma solo scoprire sotto seguenti criteri, la memoria è stata pienamente utilizzata (2,5 GB) e tutto il tempo della CPU è stata presa per eseguire GC:
-concurrent http hit del 1000/s
- mantiene lo stesso hit simultaneo per un periodo di 15 minuti
Il processo asynch registra la dimensione rimanente del CHM ogni volta che scrive nel database. Il CHM.size() mantiene intorno a Min: 300 a Max: 3500
Ho pensato che ci fosse una perdita di memoria su questa applicazione. quindi ho usato Eclipse MAT per dare un'occhiata alla discarica dell'heap. Dopo aver eseguito il Rapporto Suspect, ho ottenuto questi commenti da MAT:
Un esempio di "org.apache.catalina.session.StandardManager" caricati da "org.apache.catalina.loader.StandardClassLoader @ 0x853f0280" occupa 2.135.429,456 mila (94,76%) byte. La memoria viene accumulata in un'istanza di "java.util.concurrent.ConcurrentHashMap $ Segment []" caricato da "".
3,646,166 instances of java.util.concurrent.ConcurrentHashMap$Segment retain >= 2,135,429,456 bytes.
e
Length # Objects Shallow Heap Retained Heap
0 3,646,166 482,015,968 >= 2,135,429,456
La lunghezza 0 sopra i tradurlo registrare lunghezza vuoto all'interno del CHM (ogni volta che chiamo metodo CHM.remove()). E 'coerente al numero di record di all'interno del database, 3,646,166 record era all'interno del database quando questa discarica è stato creato
Lo scenario strana è: se mi fermo lo stress test, l'utilizzo di memoria heap gradualmente sblocco verso il basso a 25 MB. Richiede circa 30-45 minuti. Ho ri-simulare questa applicazione e le curve sembra simile al VisualVM grafico qui sotto:
Heres le domande:
1) Se questo si presenta come una perdita di memoria?
2) Ogni chiamata di rimozione remove(Object key, Object value)
per rimuovere un <key:value>
da CHM, quell'oggetto rimosso ottiene GC?
3) È qualcosa che ha a che fare con le impostazioni del GC? Ho aggiunto i seguenti parametri GC ma senza aiuto:
-XX:+UseParallelGC
-XX:+UseParallelOldGC
-XX:GCTimeRatio=19
-XX:+PrintGCTimeStamps
-XX:ParallelGCThreads=6
-verbose:gc
4) Qualsiasi idea per risolvere questo è molto apprezzata! :)
NUOVO 5) Potrebbe essere possibile perché tutti i miei riferimenti sono di riferimento? La mia comprensione è finchè la sessione HTTP è finita, tutte quelle variabili che non sono statiche sono ora disponibili per GC.
NEW Nota Ho provato a sostituire il CHM con ehcache 2.2.0, ma ottengo lo stesso problema di OutOfMemoryException. Suppongo che ehcache utilizzi anche ConcurrentHashMap.
Server Spec:
nucleo -Xeon Quad, 8 thread.
-4GB memoria
-Windows 2008 R2
-Tomcat 6.0.29
Quanto sarebbe difficile sostituire la mappa hash con un'istanza di EhCache? Queste librerie sono ottimizzate per questo tipo di attività. –
Al momento cerchiamo di non modificare molto il codice esistente perché dobbiamo ancora analizzare l'impatto. EhCache era inizialmente parte della considerazione, ma in qualche modo non era stata scelta come scelta di implementazione. – Reusable