Misurare l'utilizzo della memoria in Visual Studio (C#, Visual Basic, C++, F#)
Trova perdite di memoria e memoria non efficiente durante il debug con lo strumento di diagnostica Utilizzo memoria integrato nel debugger. Lo strumento Utilizzo memoria consente di acquisire uno o più snapshot dell'heap della memoria gestita e nativa per comprendere l'impatto sull'utilizzo della memoria da parte dei tipi di oggetto. È anche possibile analizzare l'utilizzo della memoria senza un debugger collegato o specificando come destinazione un'app in esecuzione. Per altre informazioni, vedere Eseguire strumenti di profilatura nelle build di rilascio o di debug. Per informazioni sulla scelta dello strumento di analisi della memoria migliore per le proprie esigenze, vedere Scegliere uno strumento di analisi della memoria.
Sebbene sia possibile raccogliere snapshot di memoria in qualsiasi momento nello strumento Utilizzo memoria
Importante
Gli strumenti di diagnostica integrati nel debugger sono supportati per lo sviluppo .NET in Visual Studio, tra cui ASP.NET, ASP.NET Core, sviluppo nativo/C++ e app in modalità mista (.NET e native).
In questa esercitazione si eseguiranno le seguenti attività:
- Acquisire istantanee di memoria
- Analizzare i dati di utilizzo della memoria
Se l'utilizzo della memoria non ti fornisce i dati di cui hai bisogno, altri strumenti di profilatura nel Profiler delle prestazioni forniscono diversi tipi di informazioni che potrebbero essere utili per te. In molti casi, il collo di bottiglia delle prestazioni dell'applicazione può essere causato da un elemento diverso dalla memoria dell'applicazione, ad esempio la CPU, il rendering dell'interfaccia utente o il tempo delle richieste di rete.
Nota
Supporto dell'Allocatore Personalizzato Il profiler di memoria nativa funziona raccogliendo dati di evento ETW di allocazione generati durante l'esecuzione. Gli allocatori nel CRT e nel Windows SDK sono stati annotati a livello del codice sorgente affinché i dati di allocazione possano essere acquisiti. Se stai scrivendo allocatori personalizzati, tutte le funzioni che restituiscono un puntatore alla memoria heap appena allocata possono essere decorate con __declspec(allocatore), come mostrato in questo esempio per myMalloc:
__declspec(allocator) void* myMalloc(size_t size)
Raccogliere i dati sull'utilizzo della memoria
Aprire il progetto di cui si vuole eseguire il debug in Visual Studio e impostare un punto di interruzione nell'app nel punto in cui si vuole iniziare a esaminare l'utilizzo della memoria.
Se si dispone di un'area in cui si sospetta un problema di memoria, impostare il primo punto di interruzione prima che si verifichi il problema di memoria.
Suggerimento
Poiché può essere difficile acquisire il profilo di memoria di un'operazione che ti interessa quando l'app alloca e dealloca frequentemente la memoria, imposta i punti di interruzione all'inizio e alla fine dell'operazione (o esegui l'analisi passo-passo dell'operazione) per trovare il punto esatto in cui la memoria è cambiata.
Impostare un secondo punto di interruzione alla fine della funzione o dell'area di codice che si vuole analizzare (o dopo che si verifica un sospetto problema di memoria).
La finestra strumenti di diagnostica viene visualizzata automaticamente a meno che non sia stata disattivata. Per visualizzare di nuovo la finestra, fare clic su Debug>Windows>Mostra strumenti di diagnostica.
Scegliere
Utilizzo memoria con l'impostazione Seleziona strumenti sulla barra degli strumenti. Fare clic su Debug/Avvia il debug oppure Avvia sulla barra degli strumenti oppure F5.
Al termine del caricamento dell'app, viene visualizzato il Riepilogo degli strumenti di diagnostica.
Nota
Poiché la raccolta dei dati di memoria può influire sulle prestazioni di debug delle app in modalità nativa o mista, gli snapshot di memoria sono disabilitati per impostazione predefinita. Per abilitare gli snapshot nelle app in modalità nativa o mista, avviare una sessione di debug (tasto di scelta rapida: F5). Quando viene visualizzata la finestra Strumenti di diagnostica, scegliere la scheda Utilizzo memoria e quindi scegliere Heap Profiling.
Fermare (tasto di scelta rapida: MAIUSC+F5) e riavviare il debug.
Nota
Poiché la raccolta dei dati di memoria può influire sulle prestazioni di debug delle app in modalità nativa o mista, gli snapshot di memoria sono disabilitati per impostazione predefinita. Per abilitare gli snapshot nelle app in modalità nativa o mista, avviare una sessione di debug (tasto di scelta rapida: F5). Quando viene visualizzata la finestra Strumenti di diagnostica, scegliere la scheda Utilizzo memoria, e quindi scegliere la Profilazione heap.
Stop (tasto di scelta rapida: MAIUSC+F5) e riavviare il debug.
Per creare uno snapshot all'inizio della sessione di debug, scegliere Crea snapshot sulla barra degli strumenti di riepilogo Utilizzo della memoria. Può essere utile impostare anche un punto di interruzione.
Suggerimento
Per creare una linea di base per i confronti di memoria, è consigliabile creare uno snapshot all'inizio della sessione di debug.
Eseguire lo scenario che causerà l'attivazione del primo punto di interruzione.
Mentre il debugger è sospeso al primo punto di interruzione, scegli Scatta un'istantanea sulla barra degli strumenti di riepilogo Utilizzo Memoria.
Premere F5 per eseguire l'app fino al secondo punto di interruzione.
Ora, crea un altro snapshot.
A questo punto, è possibile iniziare ad analizzare i dati.
Se hai problemi nella raccolta o visualizzazione dei dati, consulta Affrontare gli errori di profilatura e risolvere i problemi.
Analizzare i dati di utilizzo della memoria
Le righe della tabella di riepilogo Utilizzo memoria elencano gli snapshot acquisiti durante la sessione di debug e forniscono collegamenti a visualizzazioni più dettagliate.
Il nome della colonna dipende dalla modalità di debug scelta nelle proprietà del progetto: .NET, native o mixed (sia .NET che native).
Nella colonna Objects (Diff) (.NET) o Allocations (Diff) (C++) viene visualizzato il numero di oggetti in .NET o in memoria nativa quando è stato creato lo snapshot.
La colonna dimensione dell'heap (Diff) visualizza il numero di byte negli heap .NET e nativi.
Dopo aver acquisito più snapshot, le celle della tabella di riepilogo includono la modifica del valore tra lo snapshot della cella e lo snapshot precedente.
Per analizzare l'utilizzo della memoria, fare clic su uno dei collegamenti che apre un report dettagliato sull'utilizzo della memoria:
- Per visualizzare i dettagli della differenza tra lo snapshot corrente e lo snapshot precedente, scegliere il link delle modifiche a sinistra della freccia (). Una freccia rossa indica un aumento dell'utilizzo della memoria e una freccia verde indica una diminuzione.
Suggerimento
Per identificare più rapidamente i problemi di memoria, i report diff vengono ordinati in base ai tipi di oggetto che hanno aumentato maggiormente il numero complessivo (fare clic sul collegamento di modifica nella colonna Oggetti (Diff)) o che hanno aumentato maggiormente la dimensione complessiva dell'heap (fare clic sul collegamento di modifica nella colonna Dimensioni dell'heap (Diff)).
Per visualizzare i dettagli solo dello snapshot selezionato, fare clic sul collegamento non modifica.
Il report viene visualizzato in una finestra separata.
Report sui tipi gestiti
Seleziona il collegamento corrente di una cella Objects (Diff) nella tabella di Riepilogo Utilizzo Memoria.
Nota
Per il codice .NET, l'icona
Il riquadro superiore mostra il numero e le dimensioni dei tipi nello snapshot, incluse le dimensioni di tutti gli oggetti a cui fa riferimento il tipo (dimensione inclusiva).
L'albero Percorsi verso la radice nel riquadro inferiore visualizza gli oggetti che fanno riferimento al tipo selezionato nel riquadro superiore. .NET Garbage Collector pulisce la memoria per un oggetto solo quando l'ultimo tipo a cui fa riferimento è stato rilasciato.
Nell'albero Tipi a cui si fa riferimento vengono visualizzati i riferimenti contenuti nel tipo selezionato nel riquadro superiore.
Nell'albero Tipi di riferimento vengono mostrati i riferimenti detenuti dal tipo selezionato nel riquadro superiore.
Per visualizzare le istanze di un tipo selezionato nel riquadro superiore, fare clic sull'icona Visualizza Istanze accanto al tipo di oggetto.
Nella vista Istanze vengono visualizzate le istanze dell'oggetto selezionato nello snapshot nel Riquadro Superiore. Nel riquadro Percorsi verso la Radice e Oggetti Riferiti vengono visualizzati gli oggetti che fanno riferimento all'istanza selezionata e i tipi a cui fa riferimento l'istanza selezionata. Quando il debugger è fermo nel punto in cui è stato scattato lo snapshot, è possibile passare il mouse sulla cella Valore per visualizzare i valori dell'oggetto in una descrizione comando.
Report sui tipi nativi
Scegliere il collegamento corrente di una cella Allocazioni (Diff) o Heap Size (Diff) nella tabella di riepilogo Utilizzo memoria della finestra Strumenti di diagnostica.
La vista tipi mostra il numero e le dimensioni dei tipi nello snapshot.
Scegliere l'icona Visualizza istanze accanto a un tipo selezionato per visualizzare informazioni sugli oggetti del tipo selezionato nello snapshot.
La vista Istanze visualizza ogni istanza del tipo selezionato. Se si seleziona un'istanza, viene visualizzato lo stack di chiamate che ha portato alla creazione dell'istanza nel riquadro Stack di chiamate di allocazione.
Scegliere l'icona delle istanze () di un tipo selezionato per visualizzare informazioni sugli oggetti del tipo selezionato nello snapshot.
La vista istanze visualizza ogni istanza del tipo selezionato. Se si seleziona un'istanza, viene visualizzato lo stack di chiamate che ha generato la creazione dell'istanza nel riquadro Stack di chiamate di allocazione.
Scegliere Visualizzazione stack nell'elenco modalità di visualizzazione per visualizzare lo stack di allocazione per il tipo selezionato.
Informazioni dettagliate sull'utilizzo della memoria
Per la memoria gestita, lo strumento di analisi della memoria offre anche numerosi potenti approfondimenti automatici predefiniti. Selezionare la scheda Insights nei report Tipi gestiti, e verranno visualizzati i dettagli automatici applicabili come stringhe duplicate, matrici sparsee perdite di gestori di eventi.
La sezione stringhe duplicate mostra l'elenco di stringhe che vengono allocate più volte nell'heap. Inoltre, questa sezione mostra la memoria totale sprecata, ossia (numero di istanze - 1) moltiplicato per la dimensione della stringa.
La sezione matrici sparse mostra le matrici che sono principalmente riempite con zero elementi, che possono risultare inefficienti in termini di prestazioni e utilizzo della memoria. Lo strumento di analisi della memoria rileverà automaticamente queste matrici e mostrerà la quantità di memoria sprecato a causa di questi valori zero.
La sezione Event Handler Leaks, disponibile in Visual Studio 2022 versione 17.9 Preview 1, mostra potenziali perdite di memoria che possono verificarsi quando un oggetto sottoscrive l'evento di un altro oggetto. Se il publisher dell'evento sopravvive al sottoscrittore, il sottoscrittore rimane presente, anche se non ci sono altri riferimenti. Ciò può causare perdite di memoria, in cui la memoria inutilizzata non viene liberata correttamente, causando l'uso di maggiore e maggiore memoria nell'applicazione nel tempo.
Alcuni tipi sono noti per avere campi che possono essere letti per determinare le dimensioni della memoria nativa che trattengono. La scheda Approfondimenti
Report di modifica (diff)
Scegliere il collegamento di modifica in una cella della tabella di riepilogo della scheda Utilizzo memoria nella finestra Strumenti di diagnostica.
Scegli uno snapshot dall'elenco 'Confronta con ' di un report gestito o nativo.
Il report delle modifiche aggiunge colonne (contrassegnate con (Diff)) al report di base che mostra la differenza tra il valore dello snapshot di base e lo snapshot di confronto. Ecco come potrebbe apparire un report diff di tipo nativo:
Il riquadro superiore mostra il numero e le dimensioni dei tipi nello snapshot, incluse le dimensioni di tutti gli oggetti a cui fa riferimento il tipo (dimensione inclusiva).
Blog e video
Analizzare CPU e memoria durante il debug
blog di visual C++ : Profilatura della memoria in Visual C++ 2015
Passaggi successivi
In questa esercitazione si è appreso come raccogliere e analizzare i dati di utilizzo della memoria. Se hai già completato il tour del profiler, potresti voler scoprire un approccio generale all'ottimizzazione del codice con l'uso degli strumenti di profilatura.
In questa esercitazione si è appreso come raccogliere e analizzare i dati di utilizzo della memoria durante il debug. Per scoprire di più sull'analisi dell'utilizzo della memoria nelle build di rilascio, potresti voler usare il Profiler delle prestazioni.