Soppressione della raccolta dati obsoleti in C #

La mia applicazione alloca una grande quantità di memoria (milioni di piccoli oggetti per un totale di diversi gigabyte) e li trattiene per molto tempo.

  1. .NET spreca tempo a controllare tutti questi dati per fare GC su di esso?
  2. Con quale frequenza si verifica il GC Gen 2 (quello che controlla tutti gli oggetti)?
  3. C’è un modo per ridurne la frequenza o sopprimerla temporaneamente?
  4. So esattamente quando sono pronto per raccogliere una grande quantità di memoria, c’è un modo per ottimizzarlo? Attualmente sto chiamando GC.Collect (); GC.WaitForPendingFinalizers (); a quel tempo.

Aggiornamento: il contatore Perf “% Time in GC” mostra una media del 10,6%.

A meno che tu non possa confermare che il garbage collector sta rallentando triggersmente le prestazioni della tua applicazione, non dovresti prendere provvedimenti per paralizzare la funzionalità del tuo ambiente di runtime.

A giudicare dalla tua domanda, non hai confermato che il GC è un problema. Dubito fortemente che lo sia.

Ottimizza solo ciò che deve essere ottimizzato.

Guarda la proprietà System.Runtime.GCSettings.LatencyMode .

L’impostazione della proprietà GCServer su true in app.config aiuterà anche a ridurre GC (nel mio caso 10 volte meno GC quando abilitato).

Puoi fermare il garbage collector dal finalizzare uno qualsiasi dei tuoi oggetti usando il metodo statico:

 GC.SuppressFinalize(*your object*) 

Maggiori informazioni qui: link text

È ansible misurare questo utilizzando Performance Monitor. Aprire perfmon e aggiungere i contatori delle prestazioni relativi alla memoria CLR .NET. Questi contatori sono specifici del processo e con essi è ansible tenere traccia del numero di collezioni e dimensioni delle varie generazioni e in modo più specifico per voi del “% Time in GC”. Ecco il testo esplicativo per questo contatore:

% Il tempo in GC è la percentuale del tempo trascorso che è stato speso nell’esecuzione di una garbage collection (GC) dall’ultimo ciclo GC. Questo contatore è di solito un indicatore del lavoro svolto dal Garbage Collector per conto dell’applicazione per raccogliere e compattare la memoria. Questo contatore viene aggiornato solo alla fine di ogni GC e il valore del contatore riflette l’ultimo valore osservato; non è una media.

Se guardi questi contatori mentre esegui il tuo programma, dovresti avere una risposta per la frequenza e il costo del GC a causa delle tue decisioni sulla memoria.

Ecco una buona discussione dei vari contatori di prestazioni GC. Sembra che il 10% sia okay al limite.

Succede (di solito) solo quando il GC ha comunque bisogno di memoria gen2 (perché gen1 è pieno). Stai chiedendo questo in modo speculativo, o hai effettivamente un problema con GC che presta gran parte del tuo tempo di esecuzione? Se non hai un problema, ti suggerisco di non preoccuparti per il momento, ma tienilo d’occhio con i monitor delle prestazioni.

La mia applicazione ASP.NET – sistema B2B – utilizzata per iniziare a 35-40 MB quando è arrivato il primo utente. Dopo così minuti, l’applicazione cresceva fino a 180 MB con 2 o 3 utenti che toccavano pagine. Dopo aver letto le migliori pratiche di sviluppo .net e le linee guida per le prestazioni del GC, ho scoperto che il problema era il design della mia applicazione. Non ero d’accordo in una volta.

Sono rimasto inorridito da quanto facilmente possiamo fare errori. Ho rinunciato a molte funzioni e ho iniziato a semplificare alcuni oggetti. Senso:

  1. Evita di mischiare così tante pagine e controlli utente intelligenti e comunicativi (quelli con molte funzionalità che in realtà esistono maggiormente per ogni pagina che usa questo controllo).

  2. Smettere di generare funzionalità universali su classi base. A volte è preferibile ripetere. L’ereditarietà è un costo.

  3. Su alcune funzionalità complesse ho messo tutto sulla stessa funzione. SÌ, raggiungendo più di 100 linee. Quando ho letto questa raccomandazione sulla guida alle prestazioni .net non ci credevo ma funziona. Le pile di chiamate sono un problema, usare le proprietà di class su variabili locali è un problema. Le variabili di livello di class possono essere un inferno …

  4. Smetti di usare classi base complesse, non dovrebbero esistere classi base con più di 7 linee. Se diffondi classi più grandi sull’intero framework, avrai dei problemi.

  5. Inizio a utilizzare più oggetti e funzionalità statici. Ho visto l’applicazione che l’altro ragazzo ha progettato. Tutti i metodi degli oggetti dataaccess (inserire, aggiornare, eliminare, selezionare) erano quelli statici. L’applicazione con più utenti simultanei non raggiunge mai più di 45 MB.

  6. Per salvare alcuni progetti, mi piace il modello stead state. Ho imparato nel mondo reale ma l’autore Nygard è d’accordo anche con me nel suo libro: Release IT – Progettazione e distribuzione di software pronto per la produzione. Egli chiama tale approccio come modello di stato stazionario. Questo modello dice che potremmo aver bisogno di qualcosa per liberare risorse inattive.

  7. Potresti voler giocare con il file di configurazione della macchina. Sull’attributo memoryLimit verrà indicata la percentuale di memoria che potrebbe essere raggiunta prima che un processo ricicli.

  8. Si potrebbe anche voler giocare con il file di configurazione della macchina. Su questo attributo, GC determinerà il comportamento della macchina (GC di workstation e GC del server). Questa opzione può cambiare drasticamente anche il comportamento del consumo di memoria.

Ho avuto molto successo quando ho cominciato a preoccuparmi di questi oggetti. Spero che questo aiuto.

– MODIFICATO NEL 04-05-2014 Ho cambiato idea su molte cose dovute ai miglioramenti delle nuove versioni di GC e ai progressi del framework HTML 5 e MVC.