venerdì 15 luglio 2011

Perché cache di oggetti devono essere memoria sensibile - Blog ospite di Christopher André

da Michel Kopp

Christopher André è un consulente di abilitazione al servizio dynaTrace e aiuta i nostri clienti a massimizzare il loro valore escono di dynaTrace.

L'altro giorno sono andato a un cliente che stava vivendo un problema che accade abbastanza di frequente: aveva una cache che è stato in costante crescita, portando ad eccezioni OutOfMemory. Altri problemi nell'applicazione sembrava ad esso collegati.Analizzare e trovare la causa principale di questo problema di memoria legali mi ha scatenato a scrivere questo blog sul perché si imbatterono in Eccezioni OutOfMemory pur avendo una cache configurato correttamente.

Stava cercando di memorizzare nella cache i risultati della banca dati seleziona, in modo che non avrebbe dovuto eseguirli più volte. Questa è generalmente una buona idea, ma la maggior parte sviluppatori Java non so davvero come fare questo diritto e dimenticare la dimensione crescente dei loro cache.

Come possiamo avere problemi di memoria in Java?

Molto spesso, sento gli sviluppatori Java che dice "non posso avere problemi di memoria, la JVM si prende cura di tutto per me". Durante la manipolazione della memoria della JVM è grande questo non significa che non dobbiamo pensarci affatto. Anche se non facciamo errori evidenti a volte abbiamo per aiutare la JVM gestire la memoria in modo efficiente.

Il comportamento del GC è stato spiegato in diversi blog . Sarà recuperare la memoria di tutti gli oggetti che non possono essere raggiunti con i cosiddetti "Radici GC" (Radici GC sono oggetti che si presume siano sempre raggiungibili). I problemi spesso accade quando un oggetto crea molti riferimenti a oggetti diversi e e lo sviluppatore si dimentica di rilasciarli .

Riferimenti a oggetti Java e Radici GC

Riferimenti a oggetti Java e Radici GC

Cache di sistemi

La cache è, per semplificare all'estremo, una mappa. Si vuole ricordare un particolare oggetto e associarlo a un identificatore. Perché non abbiamo una scorta infinita di memoria, ci sono algoritmi specifici che sono dedicati a sfrattare alcune voci non è più necessario da questa cache. Diamo un rapido sguardo ad alcune di esse:

  • Least Recently Used (LRU)
    In questo algoritmo la cache mantiene un timestamp di accesso per ogni voce. Ogni volta che viene attivato per rimuovere le voci, a causa delle limitazioni di dimensioni aggiuntive, sarà sfrattare quelle con il timestamp più antica primo accesso.
  • Temporizzato LRU
    Questa è una forma speciale di LRU che sfrattano gli elementi sulla base di una specifica tempistica "non utilizzati" al posto di un limite di dimensione. Si tratta di uno degli algoritmi più utilizzati per la cache del database ed è stato usato nel caso del mio cliente.
  • Meno utilizzati di frequente (LFU)
    Questo algoritmo tiene traccia del numero di volte una voce è stata letta. Quando la cache cerca di sfrattare alcune delle sue voci, rimuove quelle che hanno usato almeno accede spesso.

Nonostante l'utilizzo di "temporizzata LRU" algoritmo, il mio cliente affrontato il problema che il numero di oggetti che sono stati di riferimento è cresciuto troppo grande. La memoria utilizzata da questi oggetti non poteva essere recuperato dalla JVM perché erano ancora duro a cui fa riferimento la cache. Nel suo caso la causa principale non è stato un modo inappropriato di cache di dimensioni o di una cattiva politica di sfratto. Il problema era che gli oggetti memorizzati nella cache erano troppo grandi e occupato troppa memoria. La cache non ha ancora sfrattare questi oggetti ancora in base all'algoritmo LRU temporizzata e, pertanto, il GC non poteva pretendere questi oggetti per liberare memoria.

Risolvere questo con meccanismi standard di memoria sensibile Java

Il problema causato da riferimenti concreti è stato affrontato dalla libreria Java Standard presto (versione 1.2) con oggetti di riferimento così chiamato. Ci si concentrano solo su uno di essi:. References soft
SoftReference è una classe che è stato creato espressamente per lo scopo di essere utilizzato con memoria cache-sensibili. Un riferimento Soft, secondo il javadoc ufficiale, essere "cancellati a discrezione del garbage collector in risposta alla domanda di memoria". In altre parole, il riferimento è mantenuta fino a quando non c'è bisogno di più memoria e può potenzialmente essere eliminati se la JVM ha bisogno di più memoria. Anche se le specifiche prevedono che questo può accadere in qualsiasi momento, le implementazioni so fare solo questo per evitare un OutOfMemory. Quando il Garbage Collector non è possibile liberare memoria sufficiente, sarà dereferenziare tutti SoftReferences e quindi esegue un altro Garbage Collection prima di gettare uno OutOfMemoryExcption. Se il SoftReference è l'unica cosa che tiene un albero di oggetti vivi, tutto l'albero può essere raccolta.

Nel caso del mio cliente, vorrebbe dire che la cache dovrebbe essere lavata prima di una OutOfMemoryException sarebbe attivato, impedendo che ciò accada e che lo rende un perfetto fail-safe opzione per la sua cache.

Effetti collaterali

Mentre i riferimenti soft hanno la loro utilità, nulla è privo di effetti collaterali:

Garbage Collection e domanda di memoria

Prima di tutto: una memoria cache sensibile ha spesso l'effetto che la gente taglia troppo grande. Il presupposto è che quando la cache possono essere cancellati su richiesta della memoria, dovremmo usare tutta la memoria disponibile per la cache, perché non sarà un problema. La cache sarà sempre più fino a riempire una grande porzione della memoria. Come abbiamo appreso prima di questo porta a garbage collection più lento a causa dei molti oggetti da verificare. Ad un certo punto il GC svuotare la cache e tutto sarà peachy di nuovo, giusto? Non proprio, la cache crescerà ancora. Questo è spesso scambiato per una perdita di memoria. Perché analizzatore mucchio molti trattare riferimenti morbido in modo speciale, non è facilmente reperibile.

Inoltre, gli oggetti SoftReference occupare memoria se stessi e il numero in sé di questi oggetti di riferimento morbido anche possibile creare eccezioni OutOfMemory. Questi oggetti non possono essere liquidati con il Garbage Collector! Per esempio, se si crea un oggetto SoftReference per ogni chiave e ogni valore nella vostra mappa, questi oggetti SoftReference non stanno per essere raccolti quando l'oggetto a cui puntano è raccolto. Ciò significa che si otterrà lo stesso problema come accennato in precedenza la differenza che, invece di essere causata da molti oggetti di tipo "Key" e "Valore", sarà attivato da oggetti SoftReference.

Lo schema piccolo in basso spiega come un riferimento soft in Java e funziona come un OutOfMemoryException può accadere:

Referenze morbido prima e dopo il flush

Referenze morbido prima e dopo il flush

Questo è il motivo per cui in genere non è possibile utilizzare una memoria cache sensibile senza usare gli algoritmi della cache citati: la combinazione di un algoritmo di cache di buona SoftReference sta andando a creare un sistema di cache molto robusto che dovrebbe limitare la quantità di occorrenze OutOfMemory.

Sistema di cache deve gestire lavata Referenze soft

Il vostro sistema di cache deve essere in grado di affrontare la situazione quando si svuota.Potrebbe sembrare ovvio, ma a volte si assume il valore o addirittura le chiavi della HashMap sono sempre sarà in memoria, causando alcuni NullPointerExceptions quando sono garbage collection come la cache si svuota. In entrambi i casi ha bisogno di ricaricare i dati scaricati sul successivo accesso, che alcuni cache può fare, o la cache ha bisogno di ripulire le voci lavati periodicamente e in materia di accesso (questo è ciò che la maggior parte dei sistemi fanno).

Non vi è alcuna implementazione Mappa standard utilizzando SoftReferences.

Per prevenire qualsiasi coder hard inserire commenti su WeakHashMap, lasciatemi spiegare che un WeakHashMap utilizza WeakReferences e non SoftReferences. Come un riferimento debole può essere lavato in ogni GC, anche quelle minori, non è adatto per l'implementazione della cache. Nel caso del mio cliente, la cache sarebbe stata lavata troppo spesso, non aggiunge alcun valore reale per il suo uso.

Detto questo, non disperate! L'Apache Commons Collezione biblioteca fornisce una implementazione di Map che consente di utilizzare il tipo di riferimento da utilizzare per le chiavi ed i valori in modo indipendente. Questa implementazione è la classe ReferenceMap e vi permetterà di creare la cache proprio sulla base di una mappa, senza dover sviluppare da zero.

Conclusione

Referenze morbidi per un buon mezzo per rendere i sistemi di cache più stabile. Dovrebbero essere pensato un accessorio e non una sostituzione di una politica di sfratto. Infatti molti sistemi di cache esistente li leva, ma ho incontrato molte soluzioni di cache cresciuta a casa i nostri clienti, quindi è bene sapere su questo. E infine va detto che mentre i riferimenti soft fare un sistema di cache meglio che non sono privi di effetti collaterali e dovremmo dare uno sguardo duro prima confidando che tutto va bene.

Corso Visual Studio - Corsi Visual Studio
Corso .Net- Corso Dot.Net - Corso Vb.net
Corso C# - Corso PHP - Corso Joomla

Nessun commento:

Posta un commento