From 28d2c17b0297f8616485d2ffd004ab7f612878d0 Mon Sep 17 00:00:00 2001 From: Juan Sebastian Hoyos Ayala <19413848+hoyosjs@users.noreply.github.com> Date: Fri, 13 Mar 2026 06:02:56 -0700 Subject: [PATCH] [release/10.0] Enable using CLRDATA_ENUM_MEM_HEAP2 through environment variable --- src/coreclr/debug/daccess/enummem.cpp | 10 ++++++++++ src/coreclr/inc/clrconfigvalues.h | 1 + src/coreclr/inc/dacvars.h | 1 + src/coreclr/vm/ceemain.cpp | 3 +-- src/coreclr/vm/vars.cpp | 1 + src/coreclr/vm/vars.hpp | 1 + 6 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/coreclr/debug/daccess/enummem.cpp b/src/coreclr/debug/daccess/enummem.cpp index 828ae77d6aae16..070b33578ff346 100644 --- a/src/coreclr/debug/daccess/enummem.cpp +++ b/src/coreclr/debug/daccess/enummem.cpp @@ -2021,6 +2021,16 @@ ClrDataAccess::EnumMemoryRegions(IN ICLRDataEnumMemoryRegionsCallback* callback, { DacLogMessage("EnumMemoryRegions(CLRDATA_ENUM_MEM_HEAP2)\n"); } + else if (g_EnableFastHeapDumps != 0) + { + // When the target process had DOTNET_EnableFastHeapDumps set, + // use HEAP2 which dumps loader heap pages in bulk instead of + // walking individual runtime structures. This is significantly + // faster and produces equivalent dump content since all runtime + // data structures reside in loader heaps. + flags = CLRDATA_ENUM_MEM_HEAP2; + DacLogMessage("EnumMemoryRegions(CLRDATA_ENUM_MEM_HEAP promoted to HEAP2 via DOTNET_EnableFastHeapDumps)\n"); + } else { flags = CLRDATA_ENUM_MEM_HEAP; diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h index 882a88839a933e..dd5e7dc0eaf24c 100644 --- a/src/coreclr/inc/clrconfigvalues.h +++ b/src/coreclr/inc/clrconfigvalues.h @@ -207,6 +207,7 @@ CONFIG_DWORD_INFO(UNSUPPORTED_Debugging_RequiredVersion, W("UNSUPPORTED_Debuggin #ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS RETAIL_CONFIG_DWORD_INFO(INTERNAL_MiniMdBufferCapacity, W("MiniMdBufferCapacity"), 64 * 1024, "The max size of the buffer to store mini metadata information for triage- and mini-dumps.") #endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableFastHeapDumps, W("EnableFastHeapDumps"), 0, "If non-zero, uses CLRDATA_ENUM_MEM_HEAP2 for heap dumps which enumerates loader heap pages in bulk instead of walking individual runtime data structures.") CONFIG_DWORD_INFO(INTERNAL_DbgNativeCodeBpBindsAcrossVersions, W("DbgNativeCodeBpBindsAcrossVersions"), 0, "If non-zero causes native breakpoints at offset 0 to bind in all tiered compilation versions of the given method") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_RichDebugInfo, W("RichDebugInfo"), 0, "If non-zero store some additional debug information for each jitted method") diff --git a/src/coreclr/inc/dacvars.h b/src/coreclr/inc/dacvars.h index 31a618b33d0369..38adef3ac1ff88 100644 --- a/src/coreclr/inc/dacvars.h +++ b/src/coreclr/inc/dacvars.h @@ -184,6 +184,7 @@ DEFINE_DACVAR(bool, dac__g_fProcessDetach, ::g_fProcessDetach) DEFINE_DACVAR_VOLATILE(DWORD, dac__g_fEEShutDown, ::g_fEEShutDown) DEFINE_DACVAR(ULONG, dac__g_CORDebuggerControlFlags, ::g_CORDebuggerControlFlags) +DEFINE_DACVAR(DWORD, dac__g_EnableFastHeapDumps, ::g_EnableFastHeapDumps) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pDebugger, ::g_pDebugger) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pDebugInterface, ::g_pDebugInterface) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pEEDbgInterfaceImpl, ::g_pEEDbgInterfaceImpl) diff --git a/src/coreclr/vm/ceemain.cpp b/src/coreclr/vm/ceemain.cpp index 506a371e040a62..fedaf33272699f 100644 --- a/src/coreclr/vm/ceemain.cpp +++ b/src/coreclr/vm/ceemain.cpp @@ -639,7 +639,7 @@ void EEStartupHelper() IfFailGo(EEConfig::Setup()); - + g_EnableFastHeapDumps = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_EnableFastHeapDumps); #ifdef HOST_WINDOWS InitializeCrashDump(); @@ -2223,4 +2223,3 @@ void ContractRegressionCheck() } #endif // ENABLE_CONTRACTS_IMPL - diff --git a/src/coreclr/vm/vars.cpp b/src/coreclr/vm/vars.cpp index 31fc88e6005bf0..08fe5150980730 100644 --- a/src/coreclr/vm/vars.cpp +++ b/src/coreclr/vm/vars.cpp @@ -140,6 +140,7 @@ ETW::CEtwTracer * g_pEtwTracer = NULL; GPTR_IMPL(DebugInterface, g_pDebugInterface); // A managed debugger may set this flag to high from out of process. GVAL_IMPL_INIT(DWORD, g_CORDebuggerControlFlags, DBCF_NORMAL_OPERATION); +GVAL_IMPL_INIT(DWORD, g_EnableFastHeapDumps, 0); #ifdef DEBUGGING_SUPPORTED GPTR_IMPL(EEDbgInterfaceImpl, g_pEEDbgInterfaceImpl); diff --git a/src/coreclr/vm/vars.hpp b/src/coreclr/vm/vars.hpp index 9e98fbb87cb999..af331b1ae36521 100644 --- a/src/coreclr/vm/vars.hpp +++ b/src/coreclr/vm/vars.hpp @@ -409,6 +409,7 @@ GPTR_DECL(StressLog, g_pStressLog); // GPTR_DECL(DebugInterface, g_pDebugInterface); GVAL_DECL(DWORD, g_CORDebuggerControlFlags); +GVAL_DECL(DWORD, g_EnableFastHeapDumps); #ifdef DEBUGGING_SUPPORTED GPTR_DECL(EEDbgInterfaceImpl, g_pEEDbgInterfaceImpl);