Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions eng/Version.Details.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
2 changes: 1 addition & 1 deletion eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ private bool IsIncludedInFilter(ClrNativeHeapInfo info)
sb.Append(')');

ulong wasted = 0;
if (actualSize < size && !heap.IsCurrentBlock)
if (actualSize < size && heap.State != ClrNativeHeapState.Active)
{
wasted = size - actualSize;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,32 @@ private DescribedRegion[] EnumerateAddressSpaceWorker(bool tagClrMemoryRanges, b
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}.");
Expand All @@ -119,13 +141,13 @@ private DescribedRegion[] EnumerateAddressSpaceWorker(bool tagClrMemoryRanges, b
}

// 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,
Expand All @@ -143,7 +165,7 @@ private DescribedRegion[] EnumerateAddressSpaceWorker(bool tagClrMemoryRanges, b

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);
Expand All @@ -167,7 +189,7 @@ private DescribedRegion[] EnumerateAddressSpaceWorker(bool tagClrMemoryRanges, b
DescribedRegion middleRegion = new(region)
{
Start = mem.Address,
End = mem.Address + mem.Size.Value,
End = mem.Address + mem.Size,
ClrMemoryKind = mem.Kind,
Usage = MemoryRegionUsage.CLR,
};
Expand All @@ -194,7 +216,7 @@ private DescribedRegion[] EnumerateAddressSpaceWorker(bool tagClrMemoryRanges, b
// 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);

Expand All @@ -213,15 +235,15 @@ private DescribedRegion[] EnumerateAddressSpaceWorker(bool tagClrMemoryRanges, b
// 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
};

Expand Down Expand Up @@ -265,14 +287,26 @@ private DescribedRegion[] EnumerateAddressSpaceWorker(bool tagClrMemoryRanges, b
/// <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;
Expand All @@ -286,29 +320,27 @@ private DescribedRegion[] EnumerateAddressSpaceWorker(bool tagClrMemoryRanges, b

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)
{
Expand All @@ -318,12 +350,7 @@ private static void SetRegionKindWithWarning((ulong Address, ulong? Size, ClrMem
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;
Expand Down Expand Up @@ -490,12 +517,19 @@ public enum ClrMemoryKind
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public override void Invoke()
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();
Expand Down