private static void CheckSegments(ClrHeap heap) { foreach (ClrSegment seg in heap.Segments) { Assert.NotEqual(0ul, seg.Start); Assert.NotEqual(0ul, seg.End); Assert.True(seg.Start <= seg.End); Assert.True(seg.Start < seg.CommittedEnd); Assert.True(seg.CommittedEnd < seg.ReservedEnd); if (!seg.IsEphemeralSegment) { Assert.Equal(0ul, seg.Gen0Length); Assert.Equal(0ul, seg.Gen1Length); } int count = 0; foreach (ulong obj in seg.EnumerateObjects()) { ClrSegment curr = heap.GetSegmentByAddress(obj); Assert.Same(seg, curr); count++; } Assert.True(count >= 1); } }
private static void PrintOffsets(ClrHeap heap, List <ulong> addresses) { if (addresses.Count == 0) { return; } var segments = new HashSet <ulong>(); var offsetCounts = new Dictionary <long, int>(); var previous = addresses[0]; segments.Add(heap.GetSegmentByAddress(previous).Start); foreach (var address in addresses.Skip(1)) { var offset = address > previous ? (long)(address - previous) : -(long)(previous - address); segments.Add(heap.GetSegmentByAddress(address).Start); offsetCounts[offset] = offsetCounts.TryGetValue(offset, out var count) ? count + 1 : 1; previous = address; } Console.WriteLine($"Segments count: {segments.Count}"); var sortedOffsetCounts = offsetCounts.Select(x => (offset: x.Key, count: x.Value, absOffset: Math.Abs(x.Key))).OrderBy(x => x.absOffset).ToList(); foreach (var offsetCount in sortedOffsetCounts.Take(5)) { Console.WriteLine($"Offset: {offsetCount.offset} Count: {offsetCount.count}"); } var remainingOffsets = sortedOffsetCounts.Skip(5).ToList(); if (remainingOffsets.Count != 0) { var eventsCount = remainingOffsets.Sum(x => x.count); var maxOffset = remainingOffsets.Max(x => x.absOffset); var averageOffset = (long)remainingOffsets.Average(x => x.absOffset); Console.WriteLine($"{remainingOffsets.Count} remaining offsets for {eventsCount} events, max: {maxOffset}, avg: {averageOffset}"); } }
public void AllocationContextLocation() { // Simply test that we can enumerate the heap. using DataTarget dt = TestTargets.Types.LoadFullDump(); using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); ClrHeap heap = runtime.Heap; // Ensure that we never find objects within allocation contexts. MemoryRange[] allocationContexts = heap.EnumerateAllocationContexts().ToArray(); Assert.NotEmpty(allocationContexts); foreach (MemoryRange ac in allocationContexts) { Assert.True(ac.Length > 0); ClrSegment seg = heap.GetSegmentByAddress(ac.Start); Assert.NotNull(seg); Assert.Same(seg, heap.GetSegmentByAddress(ac.End - 1)); Assert.True(seg.ObjectRange.Contains(ac)); } }
private static int?GenerationOf(ClrHeap heap, ClrObject obj) { ClrSegment segment = heap.GetSegmentByAddress(obj.Address); if (segment == null) { // This happen if the object is no longer live return(null); } else { return(segment.GetGeneration(obj)); } }
private void button3_Click(object sender, EventArgs e) { StartRuntime(); if (currObj == 0) { WriteLine("No object selected"); return; } var type = m_heap.GetObjectType(currObj); if (type.IsException) { DumpException(currObj); return; } WriteLine("==================================================="); WriteLine("000>!wdo {0:x16}", currObj); WriteLine("Address: {0:x16}", currObj); WriteLine("EE Class: {0:x16}", GetEEClass(ReadPointer(currObj))); WriteLine("Method Table: {0:x16}", ReadPointer(currObj)); WriteLine("Class Name: {0}", type.Name); WriteLine("Size: {0}", type.GetSize(currObj)); WriteLine("Instance Fields: {0}", type.Fields.Count); WriteLine("Static Fields: {0}", type.StaticFields.Count); WriteLine("Total Fields: {0}", type.Fields.Count + type.StaticFields.Count); var seg = m_heap.GetSegmentByAddress(currObj); WriteLine("Heap/Generation: {0}/{1}", seg.ProcessorAffinity, m_heap.GetGeneration(currObj)); WriteLine("Module: {0:x16}", type.Module.ImageBase); WriteLine("Assembly: {0:x16}", type.Module.AssemblyId); WriteLine("File Name: {0}", type.Module.FileName); WriteLine("Domain: {0:x16}", AdHoc.GetDomainFromMT(m_runtime, ReadPointer(currObj))); /* * foreach(var domainAddr in Hacks.GetDomainFromMT(runtime, ReadPointer(currObj)) * { * Write("{0:x16} ", domainAddr); * } * WriteLine(""); */ WriteLine("==================================================="); DumpFields(currObj); }
private static void CheckSegments(ClrHeap heap) { foreach (ClrSegment seg in heap.Segments) { Assert.NotEqual(0ul, seg.Start); Assert.NotEqual(0ul, seg.End); Assert.True(seg.Start <= seg.End); Assert.True(seg.Start < seg.CommittedMemory.End); Assert.True(seg.CommittedMemory.End < seg.ReservedMemory.End); Assert.False(seg.CommittedMemory.Overlaps(seg.ReservedMemory)); Assert.True(seg.CommittedMemory.Contains(seg.ObjectRange)); if (seg.Generation0.Length > 0) { Assert.True(seg.ObjectRange.Contains(seg.Generation0)); } if (seg.Generation1.Length > 0) { Assert.True(seg.ObjectRange.Contains(seg.Generation1)); } if (seg.Generation2.Length > 0) { Assert.True(seg.ObjectRange.Contains(seg.Generation2)); } if (!seg.IsEphemeralSegment) { Assert.Equal(0ul, seg.Generation0.Length); Assert.Equal(0ul, seg.Generation1.Length); } int count = 0; foreach (ulong obj in seg.EnumerateObjects()) { ClrSegment curr = heap.GetSegmentByAddress(obj); Assert.Same(seg, curr); count++; } Assert.True(count >= 1); } }
private static void CheckSegments(ClrHeap heap) { foreach (ClrSegment seg in heap.Segments) { Assert.AreNotEqual(0ul, seg.Start); Assert.AreNotEqual(0ul, seg.End); Assert.IsTrue(seg.Start <= seg.End); Assert.IsTrue(seg.Start < seg.CommittedEnd); Assert.IsTrue(seg.CommittedEnd < seg.ReservedEnd); if (!seg.IsEphemeral) { Assert.AreEqual(0ul, seg.Gen0Length); Assert.AreEqual(0ul, seg.Gen1Length); } foreach (ulong obj in seg.EnumerateObjectAddresses()) { ClrSegment curr = heap.GetSegmentByAddress(obj); Assert.AreSame(seg, curr); } } }
/// <summary> /// Returns the GC segment for the given object. /// </summary> /// <param name="objRef">The object reference.</param> /// <returns>IClrSegment.</returns> /// <inheritdoc /> public IClrSegment GetSegmentByAddress(ulong objRef) => Converter.Convert(Heap.GetSegmentByAddress(objRef));
public StringSummary GetTypeReferenceStringSummary(ClrType referrerType, int fieldOffset, CancellationToken token = default) { var tallyByString = new Dictionary <string, ObjectTally>(); ulong stringCount = 0; ulong stringByteCount = 0; ulong totalManagedObjectByteCount = 0; long charCount = 0; foreach (var seg in _heap.Segments) { var segType = seg.IsEphemeral ? GCSegmentType.Ephemeral : seg.IsLarge ? GCSegmentType.LargeObject : GCSegmentType.Regular; for (ulong refObj = seg.GetFirstObject(out ClrType referringType); refObj != 0; refObj = seg.NextObject(refObj, out referringType)) { if (referringType == null) { continue; } totalManagedObjectByteCount += referringType.GetSize(refObj); if (!ReferenceEquals(referringType, referrerType)) { continue; } token.ThrowIfCancellationRequested(); if (!_heap.ReadPointer(refObj + (ulong)fieldOffset, out var strObjRef) || strObjRef == 0) { continue; } var type = _heap.GetObjectType(strObjRef); if (type == null) { continue; } var value = (string)type.GetValue(strObjRef); charCount += value.Length; stringCount++; if (!tallyByString.TryGetValue(value, out var tally)) { var size = type.GetSize(strObjRef); tally = new ObjectTally(size); tallyByString[value] = tally; } var strSeg = _heap.GetSegmentByAddress(strObjRef); int generation = strSeg.GetGeneration(strObjRef); if (tally.Add(strObjRef, segType, generation)) { stringByteCount += tally.InstanceSize; } } } var uniqueStringCount = tallyByString.Count; var stringCharCount = tallyByString.Sum(s => s.Key.Length * (long)s.Value.Count); var uniqueStringCharCount = tallyByString.Keys.Sum(s => s.Length); var wastedBytes = tallyByString.Values.Sum(t => (long)t.WastedBytes); var stringOverhead = ((double)stringByteCount - (charCount * 2)) / stringCount; return(new StringSummary( tallyByString.OrderByDescending(p => p.Value.WastedBytes) .Select( p => new StringItem( p.Key, (uint)p.Key.Length, p.Value.InstanceSize, p.Value.Addresses, p.Value.CountBySegmentType, p.Value.CountByGeneration)).ToList(), totalManagedObjectByteCount, stringByteCount, (ulong)stringCharCount, (ulong)uniqueStringCharCount, stringCount, (ulong)uniqueStringCount, ulong.MaxValue, // TODO review (ulong)wastedBytes, (uint)Math.Round(stringOverhead))); }