Uh oh!
There was an error while loading. Please reload this page.
Change heap dumps to use HEAP2 as the default - #127321
Conversation
There was a problem hiding this comment.
Pull request overview
This PR changes CoreCLR heap-dump memory region enumeration to use the HEAP2 path by default, removing legacy/slow enumeration paths and createdump environment-variable workarounds.
Changes:
- Removes several legacy
EnumMemoryRegionssub-enumerations that were skipped for HEAP2 and primarily supported the older heap-dump path. - Forces heap dump generation through
CLRDATA_ENUM_MEM_HEAP2in DAC enumeration and createdump’s DAC-based region enumeration. - Simplifies the “custom dump” enumeration worker to a single mini-style path.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/coreclr/vm/threads.cpp | Removes AppDomain enumeration from thread region enumeration for non-HEAP2 legacy paths. |
| src/coreclr/vm/methodtable.cpp | Drops DispatchMap explicit enumeration for legacy non-HEAP2 dump paths. |
| src/coreclr/vm/class.cpp | Removes explicit Module + MethodDescChunk enumeration for legacy non-HEAP2 dump paths. |
| src/coreclr/vm/ceeload.cpp | Removes extensive Module hashtable/type/member explicit enumeration for legacy non-HEAP2 dump paths; keeps HEAP2 loader allocator enumeration. |
| src/coreclr/vm/assembly.cpp | Removes legacy Assembly sub-enumerations; keeps HEAP2 loader allocator enumeration only. |
| src/coreclr/debug/ee/functioninfo.cpp | Removes legacy debugger module/methoddesc/sequence-map explicit enumeration for non-HEAP2 paths. |
| src/coreclr/debug/daccess/enummem.cpp | Makes heap dumps always run via HEAP2; simplifies Custom dump worker and removes HEAP handling in wrapper. |
| src/coreclr/debug/createdump/crashinfo.cpp | Removes env-var-based opt-out/compat behavior; always uses HEAP2 for DAC-based enumeration. |
Uh oh!
There was an error while loading. Please reload this page.
Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag |
Uh oh!
There was an error while loading. Please reload this page.
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/coreclr/debug/daccess/enummem.cpp:1951
- EnumMemoryRegionsWrapper() no longer handles CLRDATA_ENUM_MEM_HEAP even though it remains a public flag in clrdata.h. Passing CLRDATA_ENUM_MEM_HEAP will now hit the debug assert and (in retail) effectively do nothing while still returning S_OK. Consider mapping HEAP -> HEAP2 for backward compatibility, or returning a failing HRESULT (e.g., E_INVALIDARG) to avoid silent success.
else if (flags == CLRDATA_ENUM_MEM_TRIAGE)
{
// triage micro-dump
status = EnumMemoryRegionsWorkerMicroTriage(flags);
}
else if (flags == CLRDATA_ENUM_MEM_HEAP2)
{
status = EnumMemoryRegionsWorkerHeap(flags);
}
else
{
_ASSERTE(!"Bad flags passing to EnumMemoryRegionsWrapper!");
}
}
Uh oh!
There was an error while loading. Please reload this page.
…untime into juhoyosa/heap2-default
Uh oh!
There was an error while loading. Please reload this page.
Fixes#122459 main PRs: - #125631 - #125459 - #127321 # Description Backports three DAC performance improvements for minidump collection: 1. **Use SHash as DAC instance hash (#125631):** Replaces the hand-rolled hash table in `DacInstanceManager` with an `SHash`-based implementation. The previous fixed-bucket hash degraded quickly for Find and insertion operations under high load. Measured ~9.5x speedup for minidump collection against a repro app with 2.5k-frame deep stacks over 50 threads. 2. **Cache debugger patches (#125459):** Caches the list of debugger breakpoint patches so that x64 stack unwinding doesn't re-scan the 1,000-bucket patch hash table on every frame. The cache is populated once on first access and invalidated on `Flush()`. Measured reduction from 55s to ~7s for minidump collection (10,000 iterations across 10 threads). 3. **Enable CLRDATA_ENUM_MEM_HEAP2 via environment variable:** When the target process has `DOTNET_EnableFastHeapDumps` set, the DAC promotes `CLRDATA_ENUM_MEM_HEAP` to `CLRDATA_ENUM_MEM_HEAP2`, which dumps loader heap pages in bulk instead of walking individual runtime structures. # Customer Impact Customers collecting minidumps of large .NET applications (many threads, deep stacks) experience extremely slow dump collection times - on the order of minutes for what should take seconds. This directly impacts incident response time in production environments. Without these fixes, dump collection through Watson/dotnet-dump/createdump remains unacceptably slow for large workloads. # Regression Yes, with respect to framework. Customers doing migrations have noticed them - framework used non-portable variants of the MSVC library. # Testing - Both PRs (#125631, #125459) were merged to main and have been stable. - Performance was measured against a repro app exercising deep stacks across many threads, confirming the expected speedups. - The env var change is gated behind an explicit opt-in (`DOTNET_EnableFastHeapDumps`), so no change in default behavior. This is the riskier change since it makes heap dump match our expectations but might yield unknown!unknown if the modules aren't indexed properly. # Risk **Low.** - The SHash and patch cache changes are confined to DAC-only code paths (`daccess.cpp`, `dacfn.cpp`, `dacimpl.h`) that execute only during diagnostic operations (dump collection, debugging). They do not affect runtime execution. - The `DOTNET_EnableFastHeapDumps` env var is opt-in and does not change default behavior. - All three changes have been running in main since March without reported issues.
Fixes#122459 main PRs: - #125631 - #125459 - #127321 # Description Backports three DAC performance improvements for minidump collection: 1. **Use SHash as DAC instance hash (#125631):** Replaces the hand-rolled hash table in `DacInstanceManager` with an `SHash`-based implementation. The previous fixed-bucket hash degraded quickly for Find and insertion operations under high load. Measured ~9.5x speedup for minidump collection against a repro app with 2.5k-frame deep stacks over 50 threads. 2. **Cache debugger patches (#125459):** Caches the list of debugger breakpoint patches so that x64 stack unwinding doesn't re-scan the 1,000-bucket patch hash table on every frame. The cache is populated once on first access and invalidated on `Flush()`. Measured reduction from 55s to ~7s for minidump collection (10,000 iterations across 10 threads). 3. **Enable CLRDATA_ENUM_MEM_HEAP2 via environment variable:** When the target process has `DOTNET_EnableFastHeapDumps` set, the DAC promotes `CLRDATA_ENUM_MEM_HEAP` to `CLRDATA_ENUM_MEM_HEAP2`, which dumps loader heap pages in bulk instead of walking individual runtime structures. # Customer Impact Customers collecting minidumps of large .NET applications (many threads, deep stacks) experience extremely slow dump collection times - on the order of minutes for what should take seconds. This directly impacts incident response time in production environments. Without these fixes, dump collection through Watson/dotnet-dump/createdump remains unacceptably slow for large workloads. # Regression Yes, with respect to framework. Customers doing migrations have noticed them - framework used non-portable variants of the MSVC library. # Testing - Both PRs (#125631, #125459) were merged to main and have been stable. - Performance was measured against a repro app exercising deep stacks across many threads, confirming the expected speedups. - The env var change is gated behind an explicit opt-in (`DOTNET_EnableFastHeapDumps`), so no change in default behavior. This is the riskier change since it makes heap dump match our expectations but might yield unknown!unknown if the modules aren't indexed properly. # Risk **Low.** - The SHash and patch cache changes are confined to DAC-only code paths (`daccess.cpp`, `dacfn.cpp`, `dacimpl.h`) that execute only during diagnostic operations (dump collection, debugging). They do not affect runtime execution. - The `DOTNET_EnableFastHeapDumps` env var is opt-in and does not change default behavior. - All three changes have been running in main since March without reported issues.
This pull request simplifies and unifies the logic for memory region enumeration when generating heap dumps. It makes HEAP2 the default heap dump and deprecates old env vars that work around slow dumps. It assumes LocaderAllocators have all necessary data. This path does a few things better and is higher perf. It enumerates the following:
Enumerates
JitManager -> Code Heaps
SystemDomain -> GlobalLoaderAllocator (was missing before partially).
AppDomain -> LoaderAllocator
Assembly -> LoaderAllocator
Module -> LoaderAllocator
LoaderAllocator -> All Loader Heaps (also collecting collectible ones now).
It skips