From 65695acccb84acebda11f3483ea8fab5c76a7d26 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Feb 2026 18:34:23 +0000 Subject: [PATCH 1/4] Initial plan From 4b2dfd8a5c046b92b3175cb559b0c6aeea54990d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Feb 2026 18:37:16 +0000 Subject: [PATCH 2/4] Add comprehensive memory analysis and diagnostics sections to dotnet-dump.md Co-authored-by: meaghanlewis <10103121+meaghanlewis@users.noreply.github.com> --- docs/core/diagnostics/dotnet-dump.md | 263 +++++++++++++++++++++++++++ 1 file changed, 263 insertions(+) diff --git a/docs/core/diagnostics/dotnet-dump.md b/docs/core/diagnostics/dotnet-dump.md index d731c0dad8911..953a6b86e2d46 100644 --- a/docs/core/diagnostics/dotnet-dump.md +++ b/docs/core/diagnostics/dotnet-dump.md @@ -317,6 +317,269 @@ StackTraceString: HResult: 80131604 ``` +## Analyzing memory leaks and allocations + +Memory leaks occur when your app holds references to objects that are no longer needed, preventing the garbage collector from reclaiming memory. Use `dotnet-dump` to identify memory leaks, find the largest objects, and understand where memory is being consumed. + +For a complete walkthrough of debugging a memory leak, see [Debug a memory leak in .NET](debug-memory-leak.md). + +### Identify the largest objects + +Use the `dumpheap` command with the `-stat` option to see a summary of objects on the heap, sorted by total size: + +```console +> dumpheap -stat + +Statistics: + MT Count TotalSize Class Name +00007f6c1eeefba8 576 59904 System.Reflection.RuntimeMethodInfo +00007f6c1dc021c8 1749 95696 System.SByte[] +00000000008c9db0 3847 116080 Free +00007f6c1e784a18 175 128640 System.Char[] +00007f6c1dbf5510 217 133504 System.Object[] +00007f6c1dc014c0 467 416464 System.Byte[] +00007f6c21625038 6 4063376 testwebapi.Controllers.Customer[] +00007f6c20a67498 200000 4800000 testwebapi.Controllers.Customer +00007f6c1dc00f90 206770 19494060 System.String +Total 428516 objects +``` + +This output shows you which types consume the most memory. In this example, `System.String` objects consume about 19 MB, and `Customer` objects consume about 4.8 MB. + +### Identify objects by namespace or assembly + +To find which modules or namespaces are consuming memory, use the `-type` option with a partial type name to filter results: + +```console +> dumpheap -type MyCompany.Data -stat + +Statistics: + MT Count TotalSize Class Name +00007f6c21625038 15000 3600000 MyCompany.Data.CustomerRecord +00007f6c21625040 8000 2560000 MyCompany.Data.OrderHistory +00007f6c21625048 2000 960000 MyCompany.Data.ProductCache +Total 25000 objects, 7120000 bytes +``` + +This approach helps you identify which parts of your codebase are responsible for memory consumption. + +### Find the highest number of instantiations + +To see which types have the most instances, regardless of total size, look at the **Count** column in the `dumpheap -stat` output. Objects with high instance counts might indicate inefficient object creation or caching issues: + +```console +> dumpheap -stat + +Statistics: + MT Count TotalSize Class Name +00007f6c1dc00f90 206770 19494060 System.String +00007f6c20a67498 200000 4800000 testwebapi.Controllers.Customer +00007f6c1dc021c8 1749 95696 System.SByte[] +``` + +In this example, there are 206,770 `String` instances and 200,000 `Customer` instances. + +### Analyze object references with gcroot + +After identifying large or numerous objects, use `gcroot` to find out why an object isn't being garbage collected. The `gcroot` command shows the reference chain from GC roots to a specific object: + +```console +> dumpheap -mt 00007f6c20a67498 + Address MT Size +00007f6ad09421f8 00007f6c20a67498 24 +... + +> gcroot 00007f6ad09421f8 + +Thread 3f68: + 00007F6795BB58A0 00007F6C1D7D0745 testwebapi.Controllers.CustomerCache.GetAll() + rbx: (interior) + -> 00007F6BDFFFF038 System.Object[] + -> 00007F69D0033570 testwebapi.Controllers.Processor + -> 00007F69D0033588 testwebapi.Controllers.CustomerCache + -> 00007F69D00335A0 System.Collections.Generic.List`1[[testwebapi.Controllers.Customer]] + -> 00007F6C000148A0 testwebapi.Controllers.Customer[] + -> 00007F6AD0942258 testwebapi.Controllers.Customer + +Found 1 root. +``` + +This output shows that the `Customer` object is held by a `CustomerCache` object, which helps you identify the source of the leak in your code. + +### Analyze memory by object size + +Use the `-min` and `-max` options to filter objects by size: + +```console +> dumpheap -min 100000 -stat + +Statistics: + MT Count TotalSize Class Name +00007f6c21625038 6 4063376 testwebapi.Controllers.Customer[] +00007f6c1dc014c0 12 416464 System.Byte[] +Total 18 objects +``` + +This command shows only objects larger than 100,000 bytes, helping you focus on the biggest memory consumers. + +## Finding deadlocks + +Use `dotnet-dump` to diagnose deadlock situations where threads are blocked waiting for resources. For a complete deadlock debugging walkthrough, see [Debug a deadlock in .NET](debug-deadlock.md). + +### List all threads + +Use the `threads` command to see all managed threads: + +```console +> threads +*0 0x1DBFF (121855) + 1 0x1DC01 (121857) + 2 0x1DC02 (121858) + ... +``` + +### Examine thread stacks + +Use `clrstack -all` to see the call stacks of all threads: + +```console +> clrstack -all +``` + +Look for patterns where multiple threads are blocked on `Monitor.Enter` or similar synchronization primitives. + +### Find lock owners + +Use the `syncblk` command to see which threads hold locks and which threads are waiting: + +```console +> syncblk +Index SyncBlock MonitorHeld Recursion Owning Thread Info SyncBlock Owner + 43 00000246E51268B8 603 1 0000024B713F4E30 5634 28 00000249654b14c0 System.Object + 44 00000246E5126908 3 1 0000024B713F47E0 51d4 29 00000249654b14d8 System.Object +``` + +The **MonitorHeld** column shows the number of threads waiting for the lock. The **Owning Thread Info** column shows which thread owns the lock. + +## Configuring symbols to avoid UNKNOWN in call stacks + +To see source file names and line numbers in call stacks instead of `UNKNOWN`, you need to configure symbol loading. + +### Enable Microsoft symbol server + +Use the `setsymbolserver` command to enable symbol downloading: + +```console +> setsymbolserver -ms +``` + +This command enables downloading symbols from the Microsoft public symbol server. + +### Load symbols for the runtime + +To download symbols for the .NET runtime, use: + +```console +> setsymbolserver -ms -loadsymbols +``` + +### Configure custom symbol paths + +If your app uses private symbols, specify a custom symbol cache directory: + +```console +> setsymbolserver -ms -cache /path/to/symbol/cache +``` + +Or add additional symbol search directories: + +```console +> setsymbolserver -ms -directory /path/to/symbols +``` + +### Verify symbol loading + +After configuring symbols, run `clrstack` again to verify that source file names and line numbers appear: + +```console +> clrstack +OS Thread Id: 0x573d (0) + Child SP IP Call Site +00007FFD28B42E20 00007FB1B18D33ED SymbolTestApp.Program.Foo4(System.String) [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 54] +00007FFD28B42ED0 00007FB1B18D2FC4 SymbolTestApp.Program.Foo2(Int32, System.String) [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 29] +``` + +For more information about symbols, see [Symbols in .NET](symbols.md). + +## GUI tools and IDE extensions + +While `dotnet-dump` is a powerful command-line tool, several GUI tools and IDE extensions provide visual memory analysis capabilities: + +### Visual Studio memory profiler + +Visual Studio includes comprehensive memory profiling tools that provide graphical views of memory usage, allocations, and object references. These tools are available on Windows. + +- **Memory Usage tool**: Provides snapshots of memory usage over time and lets you compare snapshots to identify leaks. +- **Diagnostic Tools window**: Shows real-time memory and CPU usage while debugging. +- **.NET Object Allocation Tracking**: Records all allocations and shows where objects are created. + +For more information, see [Memory Usage in Visual Studio](/visualstudio/profiling/memory-usage). + +### Visual Studio Code extensions + +While Visual Studio Code doesn't have built-in memory profiling, you can use the C# debugger to inspect objects and variables during debugging sessions: + +- **C# Dev Kit**: Provides debugging support for .NET applications. +- **Heap dump analysis**: Use `dotnet-dump` from the integrated terminal and analyze results. + +For more information, see [Debugging in Visual Studio Code](https://code.visualstudio.com/docs/csharp/debugging). + +### Other diagnostic tools + +- **dotnet-monitor**: A tool that exposes diagnostic endpoints for monitoring and collecting diagnostics artifacts. It provides HTTP endpoints that can be used to collect dumps and traces. See [dotnet-monitor](dotnet-monitor.md). +- **PerfView**: A performance analysis tool for Windows that can collect and analyze memory and CPU traces. Available at [PerfView on GitHub](https://github.com/microsoft/perfview). +- **dotnet-gcdump**: A tool specifically designed for analyzing GC heap dumps with lower overhead than full dumps. See [dotnet-gcdump](dotnet-gcdump.md). + +## Advanced memory analysis scenarios + +### Compare multiple dumps + +To understand memory growth over time, collect multiple dumps and compare them: + +1. Collect a baseline dump: `dotnet-dump collect -p -o baseline.dmp` +1. Let your app run and consume more memory +1. Collect a second dump: `dotnet-dump collect -p -o after.dmp` +1. Analyze both dumps and compare the `dumpheap -stat` results + +Look for types that have significantly more instances or larger total sizes in the second dump. + +### Analyze memory for specific object types + +To dump all instances of a specific type: + +```console +> dumpheap -type Customer + Address MT Size +00007f6ad09421f8 00007f6c20a67498 24 +00007f6ad0942210 00007f6c20a67498 24 +... +``` + +Then use `dumpobj` to examine individual objects: + +```console +> dumpobj 00007f6ad09421f8 +Name: testwebapi.Controllers.Customer +MethodTable: 00007f6c20a67498 +EEClass: 00007f6c21625000 +Size: 24(0x18) bytes +File: /app/testwebapi.dll +Fields: + MT Field Offset Type VT Attr Value Name +00007f6c1dc00f90 4000001 8 System.String 0 instance 00007f6ad09421f0 Name +00007f6c1dbf4c18 4000002 10 System.Int32 1 instance 42 Id +``` + ## Troubleshooting dump collection issues Dump collection requires the process to be able to call `ptrace`. If you are facing issues collecting dumps, the environment you are running on may be configured to restrict such calls. See our [Dumps: FAQ](faq-dumps.yml) for troubleshooting tips and potential solutions to common issues. From a802ea0045555a980b2121ca9d20d71025f7bede Mon Sep 17 00:00:00 2001 From: Meaghan Osagie Date: Wed, 11 Feb 2026 09:34:31 -0800 Subject: [PATCH 3/4] Remove symbol configuration and GUI tools sections --- docs/core/diagnostics/dotnet-dump.md | 79 ---------------------------- 1 file changed, 79 deletions(-) diff --git a/docs/core/diagnostics/dotnet-dump.md b/docs/core/diagnostics/dotnet-dump.md index 953a6b86e2d46..0a740249fee74 100644 --- a/docs/core/diagnostics/dotnet-dump.md +++ b/docs/core/diagnostics/dotnet-dump.md @@ -461,85 +461,6 @@ Index SyncBlock MonitorHeld Recursion Owning Thread Info SyncBl The **MonitorHeld** column shows the number of threads waiting for the lock. The **Owning Thread Info** column shows which thread owns the lock. -## Configuring symbols to avoid UNKNOWN in call stacks - -To see source file names and line numbers in call stacks instead of `UNKNOWN`, you need to configure symbol loading. - -### Enable Microsoft symbol server - -Use the `setsymbolserver` command to enable symbol downloading: - -```console -> setsymbolserver -ms -``` - -This command enables downloading symbols from the Microsoft public symbol server. - -### Load symbols for the runtime - -To download symbols for the .NET runtime, use: - -```console -> setsymbolserver -ms -loadsymbols -``` - -### Configure custom symbol paths - -If your app uses private symbols, specify a custom symbol cache directory: - -```console -> setsymbolserver -ms -cache /path/to/symbol/cache -``` - -Or add additional symbol search directories: - -```console -> setsymbolserver -ms -directory /path/to/symbols -``` - -### Verify symbol loading - -After configuring symbols, run `clrstack` again to verify that source file names and line numbers appear: - -```console -> clrstack -OS Thread Id: 0x573d (0) - Child SP IP Call Site -00007FFD28B42E20 00007FB1B18D33ED SymbolTestApp.Program.Foo4(System.String) [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 54] -00007FFD28B42ED0 00007FB1B18D2FC4 SymbolTestApp.Program.Foo2(Int32, System.String) [/home/mikem/builds/SymbolTestApp/SymbolTestApp/SymbolTestApp.cs @ 29] -``` - -For more information about symbols, see [Symbols in .NET](symbols.md). - -## GUI tools and IDE extensions - -While `dotnet-dump` is a powerful command-line tool, several GUI tools and IDE extensions provide visual memory analysis capabilities: - -### Visual Studio memory profiler - -Visual Studio includes comprehensive memory profiling tools that provide graphical views of memory usage, allocations, and object references. These tools are available on Windows. - -- **Memory Usage tool**: Provides snapshots of memory usage over time and lets you compare snapshots to identify leaks. -- **Diagnostic Tools window**: Shows real-time memory and CPU usage while debugging. -- **.NET Object Allocation Tracking**: Records all allocations and shows where objects are created. - -For more information, see [Memory Usage in Visual Studio](/visualstudio/profiling/memory-usage). - -### Visual Studio Code extensions - -While Visual Studio Code doesn't have built-in memory profiling, you can use the C# debugger to inspect objects and variables during debugging sessions: - -- **C# Dev Kit**: Provides debugging support for .NET applications. -- **Heap dump analysis**: Use `dotnet-dump` from the integrated terminal and analyze results. - -For more information, see [Debugging in Visual Studio Code](https://code.visualstudio.com/docs/csharp/debugging). - -### Other diagnostic tools - -- **dotnet-monitor**: A tool that exposes diagnostic endpoints for monitoring and collecting diagnostics artifacts. It provides HTTP endpoints that can be used to collect dumps and traces. See [dotnet-monitor](dotnet-monitor.md). -- **PerfView**: A performance analysis tool for Windows that can collect and analyze memory and CPU traces. Available at [PerfView on GitHub](https://github.com/microsoft/perfview). -- **dotnet-gcdump**: A tool specifically designed for analyzing GC heap dumps with lower overhead than full dumps. See [dotnet-gcdump](dotnet-gcdump.md). - ## Advanced memory analysis scenarios ### Compare multiple dumps From 83ba52cbfa0e88f1b4f527400a5fc960281849fe Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Feb 2026 00:22:40 +0000 Subject: [PATCH 4/4] Apply PR feedback: fix heading gerunds, add punctuation, update frontmatter Co-authored-by: meaghanlewis <10103121+meaghanlewis@users.noreply.github.com> --- docs/core/diagnostics/dotnet-dump.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/core/diagnostics/dotnet-dump.md b/docs/core/diagnostics/dotnet-dump.md index 0a740249fee74..da7749cab895b 100644 --- a/docs/core/diagnostics/dotnet-dump.md +++ b/docs/core/diagnostics/dotnet-dump.md @@ -1,9 +1,10 @@ --- title: dotnet-dump diagnostic tool - .NET CLI description: Learn how to install and use the dotnet-dump CLI tool to collect and analyze Windows and Linux dumps without any native debugger. -ms.date: 11/17/2020 +ms.date: 02/20/2026 ms.topic: reference ms.custom: linux-related-content +ai-usage: ai-assisted --- # Dump collection and analysis utility (dotnet-dump) @@ -317,7 +318,7 @@ StackTraceString: HResult: 80131604 ``` -## Analyzing memory leaks and allocations +## Analyze memory leaks and allocations Memory leaks occur when your app holds references to objects that are no longer needed, preventing the garbage collector from reclaiming memory. Use `dotnet-dump` to identify memory leaks, find the largest objects, and understand where memory is being consumed. @@ -377,7 +378,7 @@ Statistics: 00007f6c1dc021c8 1749 95696 System.SByte[] ``` -In this example, there are 206,770 `String` instances and 200,000 `Customer` instances. +This example shows 206,770 `String` instances and 200,000 `Customer` instances. ### Analyze object references with gcroot @@ -422,7 +423,7 @@ Total 18 objects This command shows only objects larger than 100,000 bytes, helping you focus on the biggest memory consumers. -## Finding deadlocks +## Find deadlocks Use `dotnet-dump` to diagnose deadlock situations where threads are blocked waiting for resources. For a complete deadlock debugging walkthrough, see [Debug a deadlock in .NET](debug-deadlock.md). @@ -468,9 +469,9 @@ The **MonitorHeld** column shows the number of threads waiting for the lock. The To understand memory growth over time, collect multiple dumps and compare them: 1. Collect a baseline dump: `dotnet-dump collect -p -o baseline.dmp` -1. Let your app run and consume more memory +1. Let your app run and consume more memory. 1. Collect a second dump: `dotnet-dump collect -p -o after.dmp` -1. Analyze both dumps and compare the `dumpheap -stat` results +1. Analyze both dumps and compare the `dumpheap -stat` results. Look for types that have significantly more instances or larger total sizes in the second dump.