Memory.Introspect

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.
© 2026 Memory.Introspect. All rights reserved.