Cosa c'è di sbagliato nell'usare GC.Collect ()?


103

Sebbene comprenda le gravi implicazioni del giocare con questa funzione (o almeno è quello che penso), non riesco a vedere perché sta diventando una di queste cose che programmatori rispettabili non userebbero mai, anche quelli che non lo sanno nemmeno a cosa serve.

Diciamo che sto sviluppando un'applicazione in cui l'utilizzo della memoria varia estremamente a seconda di ciò che sta facendo l'utente. Il ciclo di vita dell'applicazione può essere suddiviso in due fasi principali: modifica ed elaborazione in tempo reale. Durante la fase di editing, supponiamo che vengano creati miliardi o addirittura trilioni di oggetti; alcuni di loro piccoli e altri no, alcuni potrebbero avere finalizzatori e altri no, e supponiamo che la loro durata varia da pochi millisecondi a lunghe ore. Successivamente, l'utente decide di passare alla fase in tempo reale. A questo punto, supponiamo che le prestazioni giochino un ruolo fondamentale e che la minima alterazione nel flusso del programma possa portare conseguenze catastrofiche. La creazione di oggetti viene quindi ridotta al minimo possibile utilizzando pool di oggetti e simili, ma poi il GC si attiva in modo imprevisto e getta via tutto e qualcuno muore.

La domanda: in questo caso, non sarebbe saggio chiamare GC.Collect () prima di entrare nella seconda fase?

Dopotutto, queste due fasi non si sovrappongono mai nel tempo l'una con l'altra e tutte le ottimizzazioni e le statistiche che il GC avrebbe potuto raccogliere sarebbero state di scarsa utilità qui ...

Nota: come alcuni di voi hanno sottolineato, .NET potrebbe non essere la piattaforma migliore per un'applicazione come questa, ma questo va oltre lo scopo di questa domanda. Lo scopo è chiarire se una chiamata GC.Collect () può migliorare o meno il comportamento / le prestazioni complessive di un'applicazione. Siamo tutti d'accordo sul fatto che le circostanze in cui faresti una cosa del genere sono estremamente rare ma, di nuovo, il GC cerca di indovinare e lo fa perfettamente per la maggior parte del tempo, ma si tratta ancora di indovinare.

Grazie.


24
"la minima alterazione nel flusso del programma potrebbe portare conseguenze catastrofiche ... qualcuno potrebbe morire" - sei sicuro che C # .NET sia sufficientemente deterministico per i tuoi scopi?
Steve Jessop,

4
Né Windows né .NET sono piattaforme in tempo reale e quindi non è possibile garantire metriche delle prestazioni, almeno non sufficienti al punto da rischiare vite umane. Sono d'accordo con tutti sul fatto che o stai esagerando o sei sbadato.
Sergio Acosta

3
LOL a "una di queste cose che i programmatori rispettabili non userebbero mai, anche quelli che non sanno nemmeno a cosa serva"! I programmatori che usano roba senza sapere perché non sono certo i più rispettabili nel mio libro. :)
Il giorno

Risposte:


87

Dal blog di Rico ...

Regola n. 1

Non farlo.

Questa è davvero la regola più importante. È giusto dire che la maggior parte degli usi di GC.Collect () sono una cattiva idea e ne sono entrato in dettaglio nel post originale, quindi non ripeterò tutto qui. Quindi passiamo a ...

Regola n. 2

Considera l'idea di chiamare GC.Collect () se si è appena verificato un evento non ricorrente ed è molto probabile che questo evento abbia causato la morte di molti vecchi oggetti.

Un classico esempio di ciò è se stai scrivendo un'applicazione client e visualizzi un modulo molto grande e complicato a cui sono associati molti dati. Il tuo utente ha appena interagito con questo modulo creando potenzialmente alcuni oggetti di grandi dimensioni ... cose come documenti XML o un DataSet di grandi dimensioni o due. Quando il form si chiude, questi oggetti sono morti e quindi GC.Collect () recupererà la memoria ad essi associata ...

Quindi sembra che questa situazione possa rientrare nella Regola # 2, sai che c'è un momento nel tempo in cui molti vecchi oggetti sono morti, e non è ricorrente. Tuttavia, non dimenticare le parole d'addio di Rico.

La regola n. 1 dovrebbe prevalere sulla regola n. 2 senza prove evidenti.

Misura, misura, misura.


9
Direi che questa è solo la vecchia cosa. Niente è veramente brutto o pericoloso se sai cosa stai facendo e quindi sai quando e come farlo, così come gli effetti collaterali. Cose come non usare mai e poi mai xxxx sono messe lì per proteggere il mondo da programmatori scadenti: D
Jorge Córdoba


Non sto dicendo che usare GC.Collect è una buona pratica. Ma a volte è un modo rapido per risolvere i problemi senza conoscerne la vera causa. È brutto, lo so, ma funziona, e non mi sembra un cattivo approccio, soprattutto quando non c'è molto tempo per capire la causa principale del problema e il tuo capo è dietro di te ... sai.
Silent Sojourner

58

Se chiami GC.Collect () nel codice di produzione, stai essenzialmente dichiarando di conoscere più degli autori del GC. Potrebbe essere così. Tuttavia di solito non lo è, e quindi è fortemente sconsigliato.


3
È molto vero, ma non so se potrebbero fare supposizioni valide per tutti gli sviluppi.
MasterMastic

2
@Ken No, non possono. Ma sei in una posizione migliore per farlo? O scriverai codice assumendo hardware specifico, una specifica versione del sistema operativo e così via? Il rapporto dolore / guadagno è troppo alto su questo.
Il giorno

2
@TheDag IMO ovviamente lo sono. Quando rilascio memoria e quant'altro, non mi interessa davvero dell'hardware perché è compito del sistema operativo affrontarlo. Inoltre non mi interessa il sistema operativo perché ho un'interfaccia comune a tutti quelli per cui sto programmando. (ad esempio, non mi interessa se è Windows, Mac o Linux: quando alloco / liberi memoria in C / C ++ è nuovo / cancella malloc / dealloc). Potrei sempre sbagliarmi, quindi sentiti libero di correggermi.
MasterMastic

@MasterMastic mallocha solo un'interfaccia molto semplice e le sue implementazioni possono variare abbastanza da essere importanti. Tutto dipende dal tipo di problema che stai cercando di risolvere. Se mallocfosse "abbastanza buono", non avresti bisogno del buffer pooling, vero? Lo sviluppo in C / C ++ è pieno di esempi in cui provi a indovinare il sistema operativo / il runtime / le librerie perché lo conosci meglio (e talvolta lo sai davvero). Molte applicazioni critiche per le prestazioni evitano di utilizzare completamente gli allocatori di sistema / runtime. Giochi utilizzati per pre-allocare tutta la memoria all'avvio (array di dimensioni costanti, ecc.).
Luaan

24

Allora che ne dici di quando usi oggetti COM come MS Word o MS Excel da .NET? Senza chiamare GC.Collectdopo aver rilasciato gli oggetti COM, abbiamo scoperto che le istanze dell'applicazione Word o Excel esistono ancora.

Infatti il ​​codice che utilizziamo è:

Utils.ReleaseCOMObject(objExcel)

' Call the Garbage Collector twice. The GC needs to be called twice in order to get the
' Finalizers called - the first time in, it simply makes a list of what is to be finalized,
' the second time in, it actually does the finalizing. Only then will the object do its 
' automatic ReleaseComObject. Note: Calling the GC is a time-consuming process, 
' but one that may be necessary when automating Excel because it is the only way to 
' release all the Excel COM objects referenced indirectly.
' Ref: http://www.informit.com/articles/article.aspx?p=1346865&seqNum=5
' Ref: http://support.microsoft.com/default.aspx?scid=KB;EN-US;q317109
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()

Quindi sarebbe un uso scorretto del garbage collector? In tal caso, come facciamo a far morire gli oggetti Interop? Inoltre, se non è pensato per essere utilizzato in questo modo, perché è GCuguale il Collectmetodo di Public?


3
Ciò costituirebbe una nuova grande domanda StackOverflow, ovvero: come eliminare le istanze COM senza chiamare il GC. Con particolare riguardo ai riferimenti circolari non gestiti. È una delle sfide che mi ha reso cauto nell'aggiornamento del mio componente aggiuntivo VB6 per Outlook a C #. (Abbiamo lavorato molto per sviluppare modelli di codifica e casi di test sul lato VB che garantissero che i riferimenti COM venissero uccisi in modo deterministico quando non più necessari).
rkagerer

2
Se questo si applica agli oggetti COM in generale, forse questo è uno scenario valido. Ma subito direi che il problema è probabile che tu stia utilizzando un'applicazione client progettata per un desktop interattivo come server COM. Dalla knowledge base di MSDN: "Microsoft attualmente non consiglia e non supporta l'automazione delle applicazioni di Microsoft Office da qualsiasi applicazione o componente client non presidiato e non interattivo (inclusi ASP, ASP.NET, DCOM e NT Services), perché Office potrebbe presentare un comportamento instabile e / o un deadlock quando Office viene eseguito in questo ambiente. "
Il giorno

2
@TheDag - Microsoft potrebbe non consigliarlo, ma molti di noi hanno dovuto trasferire il vecchio codice VB6 con l'interoperabilità dell'ufficio alle app .Net Windows. Ho passato mesi di lavoro fino a quando non mi sono finalmente sbarazzato di tutti i riferimenti invisibili sospesi per un grande progetto di conversione da VB6 a .Net. Imparare a rilasciare in ordine inverso di assegnazione e mantenere riferimenti locali a OGNI singolo oggetto com, comprese le raccolte, è stato d'aiuto.
Dib

15

Bene, il GC è una di quelle cose con cui ho un rapporto di amore / odio. Lo abbiamo rotto in passato attraverso VistaDB e ne abbiamo scritto sul blog. L'hanno risolto, ma ci vuole molto tempo per ottenere soluzioni da loro su cose come questa.

Il GC è complesso e un approccio valido per tutti è molto, molto difficile da realizzare su qualcosa di così grande. MS ha svolto un lavoro abbastanza buono, ma a volte è possibile ingannare il GC.

In generale non dovresti aggiungere una a Collectmeno che tu non sappia per certo che hai appena scaricato un sacco di memoria e andrà in una crisi di mezza età se il GC non la ripulisce ora.

Puoi rovinare l'intera macchina con una serie di cattive GC.Collectaffermazioni. La necessità di un'istruzione collect indica quasi sempre un errore sottostante più ampio. La perdita di memoria di solito ha a che fare con i riferimenti e la mancanza di comprensione di come funzionano. O utilizzando degli IDisposableoggetti che non ne hanno bisogno e mettendo un carico molto più elevato sul GC.

Guarda da vicino la% di tempo trascorso in GC attraverso i contatori delle prestazioni del sistema. Se vedi che la tua app utilizza il 20% o più del suo tempo nel GC, hai seri problemi di gestione degli oggetti (o uno schema di utilizzo anomalo). Vuoi sempre ridurre al minimo il tempo speso dal GC perché velocizzerà l'intera app.

È anche importante notare che il GC è diverso sui server rispetto alle workstation. Ho visto una serie di piccoli problemi difficili da rintracciare con persone che non li testano entrambi (o che non sono nemmeno consapevoli che sono due di loro).

E giusto per essere il più completo possibile nella mia risposta, dovresti anche testare sotto Mono se stai prendendo di mira anche quella piattaforma. Poiché si tratta di un'implementazione completamente diversa, potrebbero verificarsi problemi completamente diversi rispetto all'implementazione MS.


Il colpevole sono spesso gli eventi. Ogni volta che un metodo di istanza viene utilizzato come gestore di eventi, l'editore dell'evento ha un riferimento al sottoscrittore tramite il delegato dell'evento. L'unico modo "facile" per evitare problemi è usare solo editori che sono longevi al massimo quanto gli abbonati (es. Una casella di testo che pubblica un evento gestito dal modulo che la contiene non è un problema, poiché la casella di testo non è supposta vivere fuori dalla forma). Esempio di scenario problematico: modello Singleton, viste temporanee che gestiscono gli eventi del modello.
Il giorno

5
Come si può rovinare l'intera macchina?
Adam R. Gray

13

Ci sono situazioni in cui è utile, ma in generale dovrebbe essere evitato. Potresti confrontarlo con GOTO, o in sella a un ciclomotore: lo fai quando è necessario, ma non lo dici ai tuoi amici.


12

Dalla mia esperienza non è mai stato consigliabile effettuare una chiamata a GC.Collect () nel codice di produzione. Nel debug, sì, ha i suoi vantaggi per aiutare a chiarire potenziali perdite di memoria. Immagino che la mia ragione fondamentale sia che il GC è stato scritto e ottimizzato da programmatori molto più intelligenti di me, e se arrivo a un punto che sento di dover chiamare GC.Collect () è un indizio che sono andato fuori strada da qualche parte. Nella tua situazione non sembra che tu abbia effettivamente problemi di memoria, ma solo che sei preoccupato di quale instabilità porterà la raccolta al tuo processo. Visto che non pulirà gli oggetti ancora in uso e che si adatta molto rapidamente sia alle esigenze in aumento che a quelle in calo, penso che non dovrai preoccupartene.


10

Uno dei motivi principali per chiamare GC.Collect () è quando hai appena eseguito un evento significativo che crea molta spazzatura, come quello che descrivi. Chiamare GC.Collect () può essere una buona idea qui; in caso contrario, il GC potrebbe non capire che si è trattato di un evento "una tantum".

Ovviamente dovresti profilarlo e vedere di persona.


9

Ovviamente non dovresti scrivere codice con requisiti in tempo reale in linguaggi con garbage collection non in tempo reale.

In un caso con fasi ben definite, non ci sono problemi con l'attivazione del garbage-collector. Ma questo caso è estremamente raro. Il problema è che molti sviluppatori cercheranno di usarlo per risolvere problemi di carta in uno stile cult, e aggiungerlo indiscriminatamente causerà problemi di prestazioni.


Vero. Tuttavia, i test automatizzati in grado di rilevare la condizione di errore "oggetto non idoneo per la raccolta dei rifiuti, ma dovrebbe essere" sarebbero utili. In questo modo potrebbe essere ottenuto tramite una combinazione di logica di fabbrica, logica distruttore e GC.Collect. Ad esempio, la tua classe Entity ha una proprietà IObjectTracker, normalmente nulla ma assegnata dall'entità factory di test. La fabbrica notifica anche il tracker della nascita dell'oggetto, mentre il distruttore lo notifica (quando presente) della morte. Se puoi sapere che "il distruttore è stato eseguito per tutti gli oggetti raccoglibili" puoi controllare lo stato del tracker per rilevare eventuali perdite.
Il giorno

7

La chiamata di GC.Collect () impone al CLR di eseguire uno stack walk per vedere se ogni oggetto può essere veramente rilasciato controllando i riferimenti. Ciò influirà sulla scalabilità se il numero di oggetti è elevato ed è anche noto che attiva troppo spesso la raccolta dei rifiuti. Fidati del CLR e lascia che il garbage collector si esegua quando appropriato.


2
Non solo si causa lo stack walk, ma il thread principale delle applicazioni (e tutti i thread secondari creati) vengono congelati in modo che il GC possa camminare nello stack. Più tempo trascorre la tua app in GC, più tempo rimane bloccata.
Scott Dorman,

3
Sono più preoccupato per un arresto anomalo dell'app a causa di un'eccezione di memoria insufficiente rispetto alle prestazioni lente perché l'app / GC stava buttando fuori cose che non sono più necessarie. Qualcuno sa perché Microsoft sembra lanciare un'eccezione OOM senza PRIMA buttare via la spazzatura? (Senza questo passaggio OVVIO - o almeno una spiegazione del motivo per cui questo passaggio non sembra essere stato tentato prima di lanciare un'eccezione OOM, non sono sicuro di avere alcuna fiducia nelle cose che accadono "automaticamente" nel "modo in cui dovrebbero".
Wonderbird

6

Infatti, non credo sia una cattiva pratica chiamare GC.Collect.
Ci possono essere casi in cui ne abbiamo bisogno. Ad esempio, ho un modulo che esegue un thread, che a sua volta apre tabelle diverse in un database, estrae il contenuto in un campo BLOB in un file temporaneo, crittografa il file, quindi legge il file in un flusso binario e di nuovo in un BLOB campo in un'altra tabella.

L'intera operazione richiede molta memoria e non è certo del numero di righe e della dimensione del contenuto dei file nelle tabelle.

Spesso ricevevo l'eccezione OutofMemory e ho pensato che sarebbe stato saggio eseguire periodicamente GC.Collect in base a una variabile contatore. Incremento un contatore e quando viene raggiunto un livello specificato, GC viene chiamato per raccogliere qualsiasi immondizia che potrebbe essersi formata e per recuperare la memoria persa a causa di perdite di memoria impreviste.

Dopo questo, penso che funzioni bene, almeno nessuna eccezione !!!
Chiamo nel modo seguente:

var obj = /* object utilizing the memory, in my case Form itself */
GC.Collect(GC.GetGeneration(obj ,GCCollectionMode.Optimized).

5

Sotto .net, il tempo richiesto per eseguire una garbage collection è molto più strettamente correlato alla quantità di cose che non sono spazzatura, che alla quantità di cose che lo sono. Infatti, a meno che un oggetto non sovrascriva Finalize(esplicitamente o tramite il distruttore C #), è il bersaglio di a WeakReference, si trova sul Large Object Heap, o è speciale in qualche altro modo correlato a gc, l'unica cosa che identifica la memoria in cui si trova in quanto oggetto è l'esistenza di riferimenti radicati ad esso. Altrimenti, l'operazione del GC è analoga a prendere da un edificio tutto ciò che ha valore, e dinamizzare l'edificio, costruirne uno nuovo sul sito di quello vecchio e inserirvi tutti gli oggetti di valore. Lo sforzo richiesto per dinamizzare l'edificio è totalmente indipendente dalla quantità di spazzatura al suo interno.

Di conseguenza, la chiamata GC.Collecttende ad aumentare la quantità complessiva di lavoro che il sistema deve svolgere. Ritarderà il verificarsi della raccolta successiva, ma probabilmente eseguirà immediatamente lo stesso lavoro che avrebbe richiesto la raccolta successiva quando si è verificata; nel punto in cui si sarebbe verificata la raccolta successiva, il tempo totale impiegato per la raccolta sarà stato più o meno lo stesso che GC.Collectnon era stato chiamato, ma il sistema avrà accumulato dei rifiuti, facendo sì che la raccolta successiva sia richiesta prima di quanto GC.Collectnon fosse stato stato chiamato.

Le volte che posso vedere GC.Collectdavvero utili sono quando è necessario misurare l'utilizzo della memoria di un codice (poiché le cifre sull'utilizzo della memoria sono davvero significative solo dopo una raccolta) o profilare quale di diversi algoritmi è migliore (chiamando GC.Collect () prima di eseguire ciascuna delle diverse parti di codice può aiutare a garantire uno stato di base coerente). Ci sono alcuni altri casi in cui si potrebbero sapere cose che il GC non sa, ma a meno che non si stia scrivendo un programma a thread singolo, non è possibile sapere che una GC.Collectchiamata che aiuterebbe le strutture di dati di un thread a evitare "crisi di mezza età "non avrebbe causato ai dati di altri thread una" crisi di mezza età "che altrimenti sarebbe stata evitata.


5

Creazione di immagini in un ciclo - anche se chiami dispose, la memoria non viene recuperata. La spazzatura raccoglie ogni volta. Sono passato da 1,7 GB di memoria sulla mia app per l'elaborazione delle foto a 24 MB e le prestazioni sono eccellenti.

Ci sono assolutamente del tempo che ti serve per chiamare GC.Collect.


2
Calling Disposeè non dovrebbe liberare memoria gestita. Non sembra che tu sappia come funziona il modello di memoria in .NET.
Andrew Barber

4

Si è verificato un problema simile con il Garbage Collector che non raccoglieva i rifiuti e non liberava memoria.

Nel nostro programma, stavamo elaborando alcuni fogli di calcolo Excel di dimensioni modeste con OpenXML. I fogli di calcolo contenevano ovunque da 5 a 10 "fogli" con circa 1000 righe di 14 colonne.

Il programma in un ambiente a 32 bit (x86) andrebbe in crash con un errore di "memoria insufficiente". Lo abbiamo fatto funzionare in un ambiente x64, ma volevamo una soluzione migliore.

Ne abbiamo trovato uno.

Di seguito sono riportati alcuni frammenti di codice semplificati di ciò che non ha funzionato e di ciò che ha funzionato quando si tratta di chiamare in modo esplicito Garbage Collector per liberare memoria dagli oggetti eliminati.

Chiamare il GC dall'interno della subroutine non ha funzionato. La memoria non è mai stata reclamata ...

For Each Sheet in Spreadsheets
    ProcessSheet(FileName,sheet)
Next

Private Sub ProcessSheet(ByVal Filename as string, ByVal Sheet as string)
    ' open the spreadsheet 
    Using SLDoc as SLDocument = New SLDocument(Filename, Sheet)
        ' do some work....
        SLDoc.Save
    End Using
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
End Sub

Spostando la chiamata GC all'esterno dell'ambito della subroutine, la spazzatura è stata raccolta e la memoria è stata liberata.

For Each Sheet in Spreadsheets
    ProcessSheet(FileName,sheet)
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
Next

Private Sub ProcessSheet(ByVal Filename as string, ByVal Sheet as string)
    ' open the spreadsheet 
    Using SLDoc as SLDocument = New SLDocument(Filename, Sheet)
        ' do some work....
        SLDoc.Save
    End Using
End Sub

Spero che questo aiuti gli altri che sono frustrati dalla raccolta di dati inutili .NET quando sembra ignorare le chiamate a GC.Collect().

Paul Smith


4

Non c'è niente di sbagliato nel richiedere esplicitamente una raccolta. Alcune persone vogliono solo credere che se si tratta di un servizio fornito dal venditore, non lo dubiti. Oh, e tutti quei blocchi casuali nei momenti sbagliati della tua applicazione interattiva? La prossima versione lo renderà migliore!

Lasciare che un processo in background si occupi della manipolazione della memoria significa non doverlo affrontare da soli, è vero. Ma questo non significa logicamente che sia meglio per noi non affrontarlo da soli in tutte le circostanze. Il GC è ottimizzato per la maggior parte dei casi. Ma questo non significa logicamente che sia ottimizzato in tutti i casi.

Hai mai risposto a una domanda aperta come "qual è il miglior algoritmo di ordinamento" con una risposta definitiva? In tal caso, non toccare il GC. Per quelli di voi che hanno chiesto le condizioni, o hanno fornito risposte tipo "in questo caso", potete procedere per conoscere il GC e quando attivarlo.

Devo dire che ho avuto blocchi di applicazioni in Chrome e Firefox che mi frustrano a morte, e anche allora per alcuni casi la memoria cresce senza ostacoli - Se solo imparassero a chiamare il garbage collector - o mi dessero un in modo che quando comincio a leggere il testo di una pagina posso premerlo e quindi essere libero da blocchi per i prossimi 20 minuti.


2

Penso che tu abbia ragione sullo scenario, ma non sono sicuro dell'API.

Microsoft afferma che in questi casi dovresti aggiungere la pressione della memoria come suggerimento al GC che dovrebbe presto eseguire una raccolta.


2
Interessante, ma la documentazione dice che AddMemoryPressure dovrebbe essere utilizzato quando "un piccolo oggetto gestito alloca una grande quantità di memoria NON gestita". (enfasi mia)
Robert Paulson,

2

Che cosa c'è che non va? Il fatto che tu stia cercando di indovinare il garbage collector e l'allocatore di memoria, che tra loro hanno un'idea molto più grande di te sull'effettivo utilizzo della memoria dell'applicazione in fase di esecuzione.


1
La natura euristica del Garbage Collector e il fatto che hanno esposto questa funzionalità al mondo esterno mi fanno pensare a qualcosa che è utile se usato dove deve essere. Il problema non è usarlo ma sapere come, dove e quando usarlo.
Trap

Per non parlare della migliore conoscenza dei GC su ogni altra applicazione e sulle loro esigenze di memoria. Il GC negozia la memoria con il sistema operativo e come tale è influenzato dalla memoria fisica disponibile e da tutti gli altri processi sulla macchina, sia gestiti che non gestiti. Anche se dubito che il GC sappia davvero "quando è un buon momento per raccogliere" su base "caso per caso", è molto probabile che abbia una strategia complessiva migliore rispetto a ... QUALSIASI singola applicazione. ;)
Il giorno

2

Il desiderio di chiamare GC.Collect () di solito sta cercando di coprire gli errori che hai fatto da qualche altra parte!

Sarebbe meglio se trovassi dove ti sei dimenticato di gettare le cose che non ti servono più.


5
questa è forse una generalizzazione
MickyD

1

In conclusione, puoi profilare l'applicazione e vedere come queste raccolte aggiuntive influenzano le cose. Suggerirei di starne lontano, a meno che tu non abbia intenzione di profilare. Il GC è progettato per prendersi cura di se stesso e man mano che il runtime si evolve, possono aumentare l'efficienza. Non vuoi un mucchio di codice in giro che potrebbe rovinare il lavoro e non essere in grado di trarre vantaggio da questi miglioramenti. C'è un argomento simile per l'utilizzo di foreach invece di for, ovvero che i futuri miglioramenti nascosti possono essere aggiunti a foreach e il tuo codice non deve cambiare per trarne vantaggio.


1

Lo stesso .NET Framework non è mai stato progettato per essere eseguito in un ambiente in tempo reale. Se hai davvero bisogno di un'elaborazione in tempo reale, dovresti utilizzare un linguaggio in tempo reale incorporato che non è basato su .NET o utilizzare .NET Compact Framework in esecuzione su un dispositivo Windows CE.


Potrebbe utilizzare .Net Micro Framework, progettato per ambienti in tempo reale.
TraumaPony

@TraumaPony: controlla il grafico in fondo a questa pagina msdn.microsoft.com/en-us/embedded/bb278106.aspx : Chiaramente il Micro Framework non è stato progettato per ambienti in tempo reale. Tuttavia, è stato progettato per ambienti embedded (come WinCE) ma con requisiti di alimentazione inferiori.
Scott Dorman,

1

La cosa peggiore è che il tuo programma si blocchi per un po '. Quindi se per te va bene, fallo. Di solito non è necessario per thick client o app Web con principalmente l'interazione dell'utente.

Ho scoperto che a volte i programmi con thread a esecuzione prolungata o programmi batch ottengono l'eccezione OutOfMemory anche se eliminano gli oggetti correttamente. Uno che ricordo era l'elaborazione di transazioni di database line-of-business; l'altra era una routine di indicizzazione su un thread in background in un'app thick client.

In entrambi i casi, il risultato è stato semplice: No GC.Collect, memoria esaurita, in modo coerente; GC.Collect, prestazioni impeccabili.

L'ho provato diverse altre volte per risolvere problemi di memoria, senza alcun risultato. L'ho tolto.

In breve, non inserirlo a meno che tu non riceva errori. Se lo inserisci e non risolve il problema della memoria, rimuovilo. Ricorda di provare in modalità di rilascio e confrontare le mele con le mele.

L'unica volta che le cose possono andare storte con questo è quando diventi moralista al riguardo. Non è una questione di valori; molti programmatori sono morti e sono andati direttamente in paradiso con molti GC.Collect inutili nel loro codice, che sopravvive loro.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.