Update ClrMD (#3835)
authorLee Culver <leculver@microsoft.com>
Sat, 15 Apr 2023 02:59:00 +0000 (19:59 -0700)
committerGitHub <noreply@github.com>
Sat, 15 Apr 2023 02:59:00 +0000 (02:59 +0000)
* Updates with breaking changes from ClrMD 3.0 beta

* Update NativeAddressHelper with ISOSDacInterface13 improvements

* Fix null size issue

* Fix assert

* Properly handle GCBookkeeping regions

eng/Version.Details.xml
eng/Versions.props
src/Microsoft.Diagnostics.ExtensionCommands/EEHeapCommand.cs
src/Microsoft.Diagnostics.ExtensionCommands/NativeAddressHelper.cs
src/Microsoft.Diagnostics.ExtensionCommands/ThreadPoolCommand.cs

index 00e3fcc3f4d2d475903cf79804c43de551243c39..94891f57de9672b9f48c50192f415a9293115a16 100644 (file)
@@ -4,13 +4,13 @@
       <Uri>https://github.com/dotnet/symstore</Uri>
       <Sha>0ef70c89b4f9592eade9af090b055fcac3dfd688</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Diagnostics.Runtime" Version="3.0.0-beta.23212.1">
+    <Dependency Name="Microsoft.Diagnostics.Runtime" Version="3.0.0-beta.23214.2">
       <Uri>https://github.com/microsoft/clrmd</Uri>
-      <Sha>d68eb893272971726b08473935d2c7d088d1db5c</Sha>
+      <Sha>a85ab0d3e53eb7aef4b3a2f1d595da18342e8696</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Diagnostics.Runtime.Utilities" Version="3.0.0-beta.23212.1">
+    <Dependency Name="Microsoft.Diagnostics.Runtime.Utilities" Version="3.0.0-beta.23214.2">
       <Uri>https://github.com/microsoft/clrmd</Uri>
-      <Sha>d68eb893272971726b08473935d2c7d088d1db5c</Sha>
+      <Sha>a85ab0d3e53eb7aef4b3a2f1d595da18342e8696</Sha>
     </Dependency>
   </ProductDependencies>
   <ToolsetDependencies>
index 177004a61b365920285fa10be86b86e1b9bf28df..0375194e27ddd86fb37fd728fdc603b9c96fd065 100644 (file)
@@ -45,7 +45,7 @@
     <SystemReflectionMetadataVersion>5.0.0</SystemReflectionMetadataVersion>
     <!-- Other libs -->
     <MicrosoftBclAsyncInterfacesVersion>6.0.0</MicrosoftBclAsyncInterfacesVersion>
-    <MicrosoftDiagnosticsRuntimeVersion>3.0.0-beta.23212.1</MicrosoftDiagnosticsRuntimeVersion>
+    <MicrosoftDiagnosticsRuntimeVersion>3.0.0-beta.23214.2</MicrosoftDiagnosticsRuntimeVersion>
     <MicrosoftDiaSymReaderNativePackageVersion>16.9.0-beta1.21055.5</MicrosoftDiaSymReaderNativePackageVersion>
     <MicrosoftDiagnosticsTracingTraceEventVersion>3.0.7</MicrosoftDiagnosticsTracingTraceEventVersion>
     <MicrosoftExtensionsLoggingVersion>6.0.0</MicrosoftExtensionsLoggingVersion>
index 90afe5dc430daeb2edd8ca2cb2cbd54738612fe7..a7fe9e3dd4f9701d4a8b0fa9c2cfb134741af059 100644 (file)
@@ -312,7 +312,7 @@ namespace Microsoft.Diagnostics.ExtensionCommands
                 sb.Append(')');
 
                 ulong wasted = 0;
-                if (actualSize < size && !heap.IsCurrentBlock)
+                if (actualSize < size && heap.State != ClrNativeHeapState.Active)
                 {
                     wasted = size - actualSize;
                 }
index 8a2c03cfff9425f9cb68f09a7685fbc94bdb2287..2f48a813370e2f3744c2c40b1ea49cdbefa8e46f 100644 (file)
@@ -101,10 +101,32 @@ namespace Microsoft.Diagnostics.ExtensionCommands
                     RootCacheService rootCache = runtime.Services.GetService<RootCacheService>();
                     if (clrRuntime is not null)
                     {
-                        foreach ((ulong Address, ulong? Size, ClrMemoryKind Kind) mem in EnumerateClrMemoryAddresses(clrRuntime, rootCache, includeHandleTableIfSlow))
+                        foreach ((ulong Address, ulong Size, ClrMemoryKind Kind) mem in EnumerateClrMemoryAddresses(clrRuntime, rootCache, includeHandleTableIfSlow))
                         {
-                            DescribedRegion[] found = rangeList.Where(r => r.Start <= mem.Address && mem.Address < r.End).ToArray();
+                            // The GCBookkeeping range is a large region of memory that the GC reserved.  We'll simply mark every
+                            // region within it as bookkeeping.
+                            if (mem.Kind == ClrMemoryKind.GCBookkeeping)
+                            {
+                                MemoryRange bookkeepingRange = MemoryRange.CreateFromLength(mem.Address, mem.Size);
+                                foreach (DescribedRegion region in rangeList)
+                                {
+                                    if (bookkeepingRange.Contains(region.Start))
+                                    {
+                                        if (region.State == MemoryRegionState.MEM_RESERVE)
+                                        {
+                                            region.ClrMemoryKind = ClrMemoryKind.GCBookkeepingReserve;
+                                        }
+                                        else
+                                        {
+                                            region.ClrMemoryKind = ClrMemoryKind.GCBookkeeping;
+                                        }
+                                    }
+                                }
 
+                                continue;
+                            }
+
+                            DescribedRegion[] found = rangeList.Where(r => r.Start <= mem.Address && mem.Address < r.End).ToArray();
                             if (found.Length == 0 && mem.Kind != ClrMemoryKind.GCHeapReserve)
                             {
                                 Trace.WriteLine($"Warning:  Could not find a memory range for {mem.Address:x} - {mem.Kind}.");
@@ -119,13 +141,13 @@ namespace Microsoft.Diagnostics.ExtensionCommands
                                 }
 
                                 // Add the memory range if we know its size.
-                                if (mem.Size is ulong size && size > 0)
+                                if (mem.Size > 0)
                                 {
                                     IModule module = ModuleService.GetModuleFromAddress(mem.Address);
                                     rangeList.Add(new DescribedRegion()
                                     {
                                         Start = mem.Address,
-                                        End = mem.Address + size,
+                                        End = mem.Address + mem.Size,
                                         ClrMemoryKind = mem.Kind,
                                         State = mem.Kind == ClrMemoryKind.GCHeapReserve ? MemoryRegionState.MEM_RESERVE : MemoryRegionState.MEM_COMMIT,
                                         Module = module,
@@ -143,7 +165,7 @@ namespace Microsoft.Diagnostics.ExtensionCommands
 
                             foreach (DescribedRegion region in found)
                             {
-                                if (!mem.Size.HasValue || mem.Size.Value == 0)
+                                if (mem.Size == 0)
                                 {
                                     // If we don't know the length of memory, just mark the Region with this tag.
                                     SetRegionKindWithWarning(mem, region);
@@ -167,7 +189,7 @@ namespace Microsoft.Diagnostics.ExtensionCommands
                                         DescribedRegion middleRegion = new(region)
                                         {
                                             Start = mem.Address,
-                                            End = mem.Address + mem.Size.Value,
+                                            End = mem.Address + mem.Size,
                                             ClrMemoryKind = mem.Kind,
                                             Usage = MemoryRegionUsage.CLR,
                                         };
@@ -194,7 +216,7 @@ namespace Microsoft.Diagnostics.ExtensionCommands
                                         // Region is now the starting region of this set.
                                         region.End = middleRegion.Start;
                                     }
-                                    else if (region.Size < mem.Size.Value)
+                                    else if (region.Size < mem.Size)
                                     {
                                         SetRegionKindWithWarning(mem, region);
 
@@ -213,15 +235,15 @@ namespace Microsoft.Diagnostics.ExtensionCommands
                                         // If we found no matching regions, expand the current region to be the right length.
                                         if (!foundNext)
                                         {
-                                            region.End = mem.Address + mem.Size.Value;
+                                            region.End = mem.Address + mem.Size;
                                         }
                                     }
-                                    else if (region.Size > mem.Size.Value)
+                                    else if (region.Size > mem.Size)
                                     {
                                         // The CLR memory segment is at the beginning of this region.
                                         DescribedRegion newRange = new(region)
                                         {
-                                            End = mem.Address + mem.Size.Value,
+                                            End = mem.Address + mem.Size,
                                             ClrMemoryKind = mem.Kind
                                         };
 
@@ -265,14 +287,26 @@ namespace Microsoft.Diagnostics.ExtensionCommands
         /// <summary>
         /// Enumerates pointers to various CLR heaps in memory.
         /// </summary>
-        private static IEnumerable<(ulong Address, ulong? Size, ClrMemoryKind Kind)> EnumerateClrMemoryAddresses(ClrRuntime runtime, RootCacheService rootCache, bool includeHandleTableIfSlow)
+        private static IEnumerable<(ulong Address, ulong Size, ClrMemoryKind Kind)> EnumerateClrMemoryAddresses(ClrRuntime runtime, RootCacheService rootCache, bool includeHandleTableIfSlow)
         {
             foreach (ClrNativeHeapInfo nativeHeap in runtime.EnumerateClrNativeHeaps())
             {
-                yield return (nativeHeap.Address, nativeHeap.Size, nativeHeap.Kind == NativeHeapKind.Unknown ? ClrMemoryKind.None : (ClrMemoryKind)nativeHeap.Kind);
+                Debug.Assert((int)NativeHeapKind.GCBookkeeping == (int)ClrMemoryKind.GCBookkeeping);
+
+                ClrMemoryKind kind = nativeHeap.Kind switch
+                {
+                    NativeHeapKind.Unknown => ClrMemoryKind.Unknown,
+                    > NativeHeapKind.Unknown and <= NativeHeapKind.GCBookkeeping => (ClrMemoryKind)nativeHeap.Kind, // enums match for these ranges
+                    >= NativeHeapKind.GCFreeRegion and <= NativeHeapKind.GCFreeUohSegment => ClrMemoryKind.GCHeapToBeFreed,
+                    _ => ClrMemoryKind.Unknown
+                };
+
+                yield return (nativeHeap.Address, nativeHeap.Size ?? 0, kind);
             }
 
-            if (includeHandleTableIfSlow)
+            // .Net 8 and beyond has accurate HandleTable memory info.
+            bool haveAccurateHandleInfo = runtime.ClrInfo.Flavor == ClrFlavor.Core && runtime.ClrInfo.Version.Major >= 8;
+            if (includeHandleTableIfSlow && !haveAccurateHandleInfo)
             {
                 ulong prevHandle = 0;
                 ulong granularity = 0x100;
@@ -286,29 +320,27 @@ namespace Microsoft.Diagnostics.ExtensionCommands
 
                     if (handle.Address < prevHandle || handle.Address >= (prevHandle | (granularity - 1)))
                     {
-                        yield return (handle.Address, null, ClrMemoryKind.HandleTable);
+                        yield return (handle.Address, 0, ClrMemoryKind.HandleTable);
                         prevHandle = handle.Address;
                     }
                 }
             }
 
-            // We don't really have the true bounds of the committed or reserved segments.
-            // Return null for the size so that we will mark the entire region with this type.
             foreach (ClrSegment seg in runtime.Heap.Segments)
             {
                 if (seg.CommittedMemory.Length > 0)
                 {
-                    yield return (seg.CommittedMemory.Start, null, ClrMemoryKind.GCHeap);
+                    yield return (seg.CommittedMemory.Start, seg.CommittedMemory.Length, ClrMemoryKind.GCHeap);
                 }
 
                 if (seg.ReservedMemory.Length > 0)
                 {
-                    yield return (seg.ReservedMemory.Start, null, ClrMemoryKind.GCHeapReserve);
+                    yield return (seg.ReservedMemory.Start, seg.ReservedMemory.Length, ClrMemoryKind.GCHeapReserve);
                 }
             }
         }
 
-        private static void SetRegionKindWithWarning((ulong Address, ulong? Size, ClrMemoryKind Kind) mem, DescribedRegion region)
+        private static void SetRegionKindWithWarning((ulong Address, ulong Size, ClrMemoryKind Kind) mem, DescribedRegion region)
         {
             if (region.ClrMemoryKind != mem.Kind)
             {
@@ -318,12 +350,7 @@ namespace Microsoft.Diagnostics.ExtensionCommands
                 if (region.ClrMemoryKind is not ClrMemoryKind.None
                     and not ClrMemoryKind.HighFrequencyHeap)
                 {
-                    if (mem.Size is not ulong size)
-                    {
-                        size = 0;
-                    }
-
-                    Trace.WriteLine($"Warning:  Overwriting range [{region.Start:x},{region.End:x}] {region.ClrMemoryKind} -> [{mem.Address:x},{mem.Address + size:x}] {mem.Kind}.");
+                    Trace.WriteLine($"Warning:  Overwriting range [{region.Start:x},{region.End:x}] {region.ClrMemoryKind} -> [{mem.Address:x},{mem.Address + mem.Size:x}] {mem.Kind}.");
                 }
 
                 region.ClrMemoryKind = mem.Kind;
@@ -490,12 +517,19 @@ namespace Microsoft.Diagnostics.ExtensionCommands
             StubHeap,
             HighFrequencyHeap,
             LowFrequencyHeap,
+            ExecutableHeap,
+            FixupPrecodeHeap,
+            NewStubPrecodeHeap,
+            ThunkHeap,
+            HandleTable,
+            GCBookkeeping,
 
             // Skip ahead so new ClrMD NativeHeapKind values don't break the enum.
             Unknown = 100,
             GCHeap,
+            GCHeapToBeFreed,
             GCHeapReserve,
-            HandleTable,
+            GCBookkeepingReserve,
         }
 
         public sealed class DescribedRegion : IMemoryRegion
index 074bb5321d1c2270a1008d28c23b700d259ea988..8736bcc4fb6098c28bba4df74c59d801d2a298cf 100644 (file)
@@ -96,7 +96,7 @@ namespace Microsoft.Diagnostics.ExtensionCommands
                         foreach (HillClimbingLogEntry entry in hcl)
                         {
                             Console.CancellationToken.ThrowIfCancellationRequested();
-                            output.WriteRow($"{(entry.TickCount - end)/1000.0:0.00}", entry.StateOrTransition, entry.NewControlSetting, entry.LastHistoryCount, $"{entry.LastHistoryMean:0.00}");
+                            output.WriteRow($"{(entry.TickCount - end)/1000.0:0.00}", entry.StateOrTransition, entry.NewThreadCount, entry.SampleCount, $"{entry.Throughput:0.00}");
                         }
 
                         Console.WriteLine();