2009-07-19 8 views

risposta

9

Il punto di AddMemoryPressure è di dire al garbage collector che c'è una grande quantità di memoria allocata con quell'oggetto. Se non è gestito, il garbage collector non lo sa; solo la parte gestita. Dato che la porzione gestita è relativamente piccola, il GC potrebbe lasciarlo passare più volte per la raccolta dei dati inutili, essenzialmente sprecando memoria che potrebbe dover essere liberata.

Sì, è ancora necessario allocare manualmente e deallocare la memoria non gestita. Non puoi andartene da quello. Basta usare AddMemoryPressure per assicurarsi che il GC sappia che è lì.

Edit:

Ebbene, nel caso in cui uno, ho potuto farlo, ma sarebbe fare grande differenza, come il GC non sarebbe in grado di fare una cosa per il mio tipo , se ho capito bene: 1) dichiarerei la mia variabile, 8 byte gestiti, 2mb byte non gestiti. Lo userei poi, chiamerei dispose, quindi la memoria non gestita viene liberata. In questo momento si occuperà solo di 8 byte. Ora, ai miei occhi, avendo chiamato AddMemoryPressure all'inizio e RemoveMemoryPressure alla fine non avrei reso nulla di diverso. Cosa sto sbagliando? Mi dispiace per essere così entusiasta di questo. - Jorge Branco

Penso di vedere il tuo problema.

Sì, se è possibile garantire che si chiami sempre Dispose, quindi sì, non è necessario preoccuparsi di AddMemoryPressure e RemoveMemoryPressure. Non c'è equivalenza, poiché il riferimento esiste ancora e il tipo non verrebbe mai raccolto.

Detto questo, si desidera comunque utilizzare AddMemoryPressure e RemoveMemoryPressure, per completezza. Cosa succede se, ad esempio, l'utente della tua classe ha dimenticato di chiamare Dispose?In tal caso, supponendo che tu abbia implementato correttamente il modello di Smaltimento, finirai per reclamare i tuoi byte non gestiti al momento della finalizzazione, cioè quando l'oggetto gestito viene raccolto. In tal caso, si desidera che la pressione della memoria sia ancora attiva, in modo che l'oggetto abbia maggiori probabilità di essere recuperato.

+0

Beh, questo non ha risposto alla domanda, lol. –

+0

Ho detto quasi esattamente quello che ha detto Steven Lyons, solo in un modo diverso. Come non ha risposto alla domanda? – Randolpho

+0

Beh, in realtà l'ho riletto e modificato il mio post. –

13

Viene fornito in modo che il GC conosca il costo reale dell'oggetto durante la raccolta. Se l'oggetto è effettivamente più grande di quanto la dimensione gestita rispecchia, potrebbe essere un candidato per la raccolta rapida (e).

Brad Abrams entry a questo proposito è abbastanza chiaro:

consideri una classe che ha una piccola Dimensioni gestite grado, ma contiene un puntatore ad un grande pezzo di memoria non gestita. Anche dopo che nessuno fa riferimento all'istanza gestita, lo potrebbe rimanere attivo per un po 'perché il GC vede solo la dimensione dell'istanza gestita non ritiene che "valga it" per liberare l'istanza. Quindi abbiamo bisogno di per "insegnare" al GC sul costo effettivo di questa istanza in modo che sappia esattamente quando kickare una collezione per liberare altra memoria nel processo .

+0

In realtà, ora che rileggo il tuo post, la mia domanda rimane ferma. Dopo aver usato la mia bitmap, chiamerò dispose su di esso, quindi in realtà richiederà solo 8 byte di memoria. Se, d'altro canto, non ho chiamato dispose, beh, allora in realtà si ottengono 2 MB di memoria. C'è il terzo caso in cui non esiste un metodo di smaltimento, quindi il GC non può fare nulla per questo. Quindi, il GC che conosce la dimensione reale del tipo aiuterà solo nella situazione 2. O mi manchi qualcosa? –

+0

Nel caso 1, sarà necessario chiamare GC.AddMemoryPressure sull'allocazione bitmap e quindi GC.RemoveMemoryPressure quando si rilascia manualmente la bitmap. Ciò garantirà che l'oggetto rifletta correttamente le sue dimensioni sul GC. Tuttavia, se esiste un modo per essere sicuri che il GC non venga mai eseguito mentre il tuo oggetto è idoneo per la raccolta e la bitmap è allocata, questi metodi potrebbero non avere importanza. –

+0

Beh, nel caso uno, potrei farlo, ma non farebbe alcuna differenza, in quanto il GC non sarebbe in grado di fare una cosa del mio tipo, se ho capito bene: 1) dichiarerei il mio variabile, 8 byte gestiti, 2mb byte non gestiti. Lo userei poi, chiamerei dispose, quindi la memoria non gestita viene liberata. In questo momento si occuperà solo di 8 byte. Ora, ai miei occhi, avendo chiamato AddMemoryPressure all'inizio e RemoveMemoryPressure alla fine non avrei reso nulla di diverso. Cosa sto sbagliando? Mi dispiace per essere così entusiasta di questo. –

2

In questo modo, assumendo sempre gli oggetti gestiti a 8 byte ciascuno riferendosi a un'immagine non gestita da 2 MB. Il GC potrebbe attendere molto prima di raccogliere centinaia o migliaia di piccoli oggetti gestiti, perché sono così piccoli. Ciò significherebbe che anche centinaia o migliaia di blocchi non gestiti collegati da 2 MB rimarranno vivi, in attesa della rimozione. Questo potrebbe diventare un grosso problema. Aggiungendo 2 MB di pressione di memoria nel costruttore, farai in modo che GC pensi che l'oggetto gestito non sia grande 8 byte ma 8 byte + 2 MB. Ciò attiverà il modo di raccolta prima.

Non dimenticare la chiamata di rimozione.

Naturalmente se ti disponi, allora non avrai bisogno di tutto questo.