Dump types
Memory.Introspect produces three different artefacts. They are not interchangeable — pick the one that matches the question you're trying to answer.
Quick reference
| API | Output | Best for | Open in |
|---|---|---|---|
CollectMemoryGraphAsync |
.gcdump (managed heap graph) |
"What managed objects exist? Who holds references to what?" | PerfView, Visual Studio |
DumpAsync |
Full process dump (.dmp / core file) |
"Snapshot every byte of memory, including unmanaged state." | WinDbg, dotnet-dump, LLDB |
CollectSamplingProfileAsync |
SamplingProfileResult (managed) |
"Which methods are using the most CPU right now?" | Inspect the result object directly |
Memory graph (.gcdump)
The output of CollectMemoryGraphAsync. A compact graph of every managed object on the heap at the moment a GC fired — type, size, and outgoing references — but not the field contents.
A .gcdump is much smaller than a full process dump (megabytes vs. gigabytes for the same process) and shows you exactly what a memory profiler would: type histograms, retention paths, and the GC root for any object.
Use it to answer:
- "Why is this process using 4 GB of memory?"
- "Why is this object still alive after I disposed it?"
- "Who's holding a reference to my
HttpClient?"
var result = await introspector.CollectMemoryGraphAsync(pid);
result.SaveToDisk("snapshot.gcdump");
See Capturing memory graphs for the full guide.
Process dump (.dmp / core)
The output of DumpAsync. The same format produced by dotnet-dump collect — a binary snapshot of the entire process address space.
A process dump captures everything: managed and unmanaged memory, thread stacks, register state, loaded modules. It's the right tool when you need to inspect unmanaged state, debug a crash, or analyse a hang.
CollectionType controls the trade-off between dump completeness and file size:
await introspector.DumpAsync(pid, "snapshot.dmp", Dumper.CollectionType.Heap);
Use it to answer:
- "Why did this process crash?"
- "What does the unmanaged side of this interop look like right now?"
- "Threads are deadlocked — what stack is each one on?"
Process dumps are large — plan storage accordingly.
Sampling profile
The output of CollectSamplingProfileAsync. A time-bounded capture that samples thread stacks at a fixed rate and reports the methods that appear most often.
This is different from the memory APIs: it doesn't capture a heap, it captures time. The result is a SamplingProfileResult you read directly:
var profile = await introspector.CollectSamplingProfileAsync(pid, TimeSpan.FromSeconds(30));
foreach (var method in profile.TopMethods.Take(10))
{
Console.WriteLine($"{method.SampleCount,6} {method.Name}");
}
Use it to answer:
- "Which methods are using the most CPU right now?"
- "Where is this batch job spending its time?"
- "Is the bottleneck in my code or in a library?"
See Sampling profiles for the full guide and the available configuration options (SamplingExcludedModules, CircularBufferSizeInMB, etc.).
Which one do I want?
- Memory grew unexpectedly → memory graph.
- Process crashed or hung → process dump.
- Process is slow / hot CPU → sampling profile.
- Mix of the above → capture more than one. The three APIs are independent and can be called from the same
MemoryIntrospector.