From f0fc5f8e2ce471f4c5e4afc41d2920a5f5ccd1b0 Mon Sep 17 00:00:00 2001 From: Lee Culver Date: Thu, 12 Oct 2023 11:59:35 -0700 Subject: [PATCH] !maddress misattributes memory to the GC (#4318) Fixes an issue reported by the GC team. On windows, VirtualQuery information (bounds of allocated segments) is very accurate in dumps because we have an entire segment of the dump format which describes it. On Linux, it seems like we smash together regions which came from two different calls of VirtualAlloc (well, the Linux equivalent). So, only use a heuristic of attributing regions of allocated memory on Windows. Additionally, we are 100% accurate in reporting every byte of memory that the GC allocates as of .Net 8. We shouldn't be ever using this heuristic to attribute any memory to the GC. --- .../NativeAddressHelper.cs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Diagnostics.ExtensionCommands/NativeAddressHelper.cs b/src/Microsoft.Diagnostics.ExtensionCommands/NativeAddressHelper.cs index 7de6a766a..409c85bcf 100644 --- a/src/Microsoft.Diagnostics.ExtensionCommands/NativeAddressHelper.cs +++ b/src/Microsoft.Diagnostics.ExtensionCommands/NativeAddressHelper.cs @@ -196,7 +196,25 @@ namespace Microsoft.Diagnostics.ExtensionCommands // by the other region kind. if (region.ClrMemoryKind == ClrMemoryKind.None) { - region.ClrMemoryKind = mem.Kind; + // On platforms other than Windows, we may not have accurate region begin/end + // locations. For example, with Windows dumps, we will get two distinct regions + // when one call to virtual alloc maps 0x10000-0x20000 and a different call to + // virtual alloc maps 0x20000-0x30000. On Linux, we seem to only get one region + // defined (0x10000-0x30000) even if that came from two different calls to + // the Linux equivalent of VirtualAlloc. Therefore, we only use this heuristic + // to tag memory on Windows to avoid accidently over-attributing memory to CLR. + // + // Finally, we actually get very accurate data about GC structures, so never + // use this heuristic to tag memory as belonging to the GC because we know it + // doesn't. + if (Target.OperatingSystem == OSPlatform.Windows + && mem.Kind != ClrMemoryKind.GCHeap + && mem.Kind != ClrMemoryKind.GCHeapReserve + && mem.Kind != ClrMemoryKind.GCBookkeeping + && mem.Kind != ClrMemoryKind.GCHeapToBeFreed) + { + region.ClrMemoryKind = mem.Kind; + } } DescribedRegion middleRegion = new(region) -- 2.34.1