Change heap dumps to use HEAP2 as the default#127321
Merged
Merged
Conversation
Contributor
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. |
Contributor
|
Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag |
rcj1
approved these changes
Apr 23, 2026
am11
reviewed
Apr 23, 2026
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
am11
reviewed
Apr 23, 2026
am11
reviewed
Apr 23, 2026
hoyosjs
commented
Apr 23, 2026
hoyosjs
commented
Apr 23, 2026
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Contributor
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!");
}
}
…untime into juhoyosa/heap2-default
Closed
This was referenced May 11, 2026
hoyosjs
added a commit
that referenced
this pull request
May 13, 2026
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.
hoyosjs
added a commit
that referenced
this pull request
May 13, 2026
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 file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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