Come utilizzo un file di dettagli per diagnosticare una perdita di memoria?

Ho un servizio .NET con un normale set di lavoro privato di circa 80 MB. Durante un recente test di caricamento, il processo ha raggiunto l’utilizzo di memoria da 3,5 GB, causando l’esaurimento della memoria fisica dell’intero computer (3,9 GB su 4 utilizzati) e la memoria non è stata rilasciata molto tempo dopo l’interruzione del test di caricamento. Usando il task manager, ho preso un file di dump del processo e l’ho aperto in Visual Studio 2010 SP1, e sono in grado di avviare il debug su di esso.

Come diagnosticare il problema di memoria? Ho dotTrace Memory 3.x a mia disposizione, supporta la profilazione della memoria sui file di dump? In caso contrario, le funzionalità di profilatura della memoria di Visual Studio 2010 Premium (attualmente sono Professional)? WinDbg può aiutare?

AGGIORNAMENTO: il nuovo Visual Studio 2013 Ultimate ora può diagnosticare in modo nativo i problemi di memoria utilizzando i file di dump. Vedi questo post sul blog per maggiori dettagli.

Installa WinDbg. È necessario assicurarsi di ottenere la versione corretta x86 o x64 a seconda del dump. Ecco un link diretto al download per x86.

Su questo, è necessario assicurarsi di aver preso la discarica corretta. È ansible utilizzare Task Manager per creare il file di dump (fare clic con il tasto destro del mouse su process -> Create Dump File). Se sei su 64 bit e il tuo processo è x86 usa la versione a 32 bit di Task Manager (C: \ Windows \ SysWOW64 \ taskmgr.exe) per prendere il file dump. Vedi il mio articolo per maggiori informazioni sulla presa di file dump, ad esempio se sei su XP e hai bisogno di usare windbg per creare il file dump.

avviso c’è una curva di apprendimento abbastanza ripida e le cose potrebbero non funzionare esattamente come descritto qui, quindi tornare con eventuali problemi.

Suppongo che tu stia usando .NET4 dato che puoi aprire il dump in Visual Studio. Ecco una guida molto rapida per aiutarti a lavorare con il tuo file dmp:

1) Esegui WinDbg, imposta il percorso dei simboli (File -> Percorso di ricerca dei simboli) su

SRV*c:\symbols*http://msdl.microsoft.com/download/symbols 

2) Apri il dump di Crash o trascina il file .DMP su WinDbg.

3) digita questo nella finestra di comando

 .loadby sos clr 

(FYI, per .NET 2, il comando dovrebbe essere .loadby sos mscorwks )

4) quindi digita questo

 !dumpheap -stat 

che elenca il tipo di oggetti e il loro conteggio. sembra qualcosa del genere:

inserisci la descrizione dell'immagine qui

Dovrai analizzare questo nel contesto della tua applicazione e vedere se qualcosa sembra insolito.

C’è molto di più da windbg, google è tuo amico.

Generalmente, se si ha una perdita in un’applicazione gestita, significa che qualcosa non viene raccolto. Le fonti comuni includono

  • Gestori di eventi: se l’utente non viene rimosso, il publisher lo terrà attivo.

  • statica

  • Finalizzatori: un finalizzatore bloccato impedirà al thread del finalizzatore di eseguire altri finalizzatori e quindi impedire la raccolta di tali istanze.

  • Allo stesso modo, un thread con deadlock si aggrappa a qualunque radice detenga. Naturalmente se si hanno thread deadlock che probabilmente interesseranno l’applicazione su più livelli.

Per risolvere questo problema è necessario ispezionare l’heap gestito. WinDbg + SOS (o PSSCOR) ti consentirà di farlo. Il comando !dumpheap -stat elenca l’intero heap gestito.

È necessario avere un’idea del numero di istanze di ciascun tipo da prevedere nell’heap. Una volta trovato qualcosa di strano, puoi usare il !dumpheap -mt per elencare tutte le istanze di un determinato tipo.

Il prossimo passo è analizzare la radice di queste istanze. Scegline uno a caso e fai un !gcroot su quello. Questo mostrerà come quella particolare istanza è radicata. Cerca i gestori di eventi e gli oggetti bloccati (di solito rappresentano riferimenti statici). Se vedi la coda del finalizzatore lì, devi esaminare cosa sta facendo il thread del finalizzatore. Usa i comandi !threads e !clrstack per quello.

Se tutto sembra a posto per quell’istanza, ti sposti su un’altra istanza. Se ciò non produce nulla, potrebbe essere necessario tornare indietro per esaminare di nuovo l’heap e ripetere da lì.

Altre fonti di perdite includono: assembly che non vengono scaricati e frammentazione del Large Object Heap. SOS / PSSCOR può aiutarti a localizzare anche questi, ma per ora salterò i dettagli.

Se vuoi saperne di più, ti consiglio il blog di Tess . Ho anche fatto un paio di video su come usare WinDbg + SOS ( qui e qui ).

Se hai la possibilità di eseguire il debug del processo mentre è in esecuzione, ti consiglio di utilizzare PSSCOR anziché SOS. PSSCOR è essenzialmente un ramo privato delle sorgenti SOS che è stato migliorato con comandi aggiuntivi e molti dei comandi SOS esistenti sono stati migliorati. Ad esempio, la versione !dumpheap comando !dumpheap ha una colonna delta molto utile, che semplifica molto la ricerca di perdite di memoria.

Per utilizzarlo è necessario avviare il processo, albind WinDbg e caricare PSSCOR e fare un !dumpheap -stat . Quindi lasci che il processo venga eseguito di nuovo in modo da creare allocazioni. Interrompere l’esecuzione e ripetere il comando. Ora PSSCOR mostrerà il numero di istanze aggiunte / rimosse dall’ispezione precedente.

Dalla versione 2017.2 JetBrains dotMemory supporta l’analisi dei dump della memoria di Windows con tutta la sua potente e acctriggersnte interfaccia grafica.

http://msdn.microsoft.com/en-us/library/ee817660.aspx

Microsoft ha una guida qui. Tuttavia, è troppo difficile per i principianti.

dotTrace può generare grafici di memoria visiva (meglio di WinDbg), ma non usarli mai per i dump.