/// <summary> /// Print type statistics diff. /// </summary> /// <param name="typeInfos"></param> /// <param name="typeInfos2"></param> /// <param name="vmmap"></param> /// <param name="vmmap2"></param> /// <param name="topN"></param> /// <param name="orderBySize"></param> /// <param name="minCount"></param> /// <returns>Allocated memory diff in KB. If VMmap data is present the total allocated memory diff for allocated managed heap, heap, private, file mappings and sharable memory is returned.</returns> private int PrintTypeStatisticsDiff(List <TypeInfo> typeInfos, List <TypeInfo> typeInfos2, VMMapData vmmap, VMMapData vmmap2, int topN, int minCount, bool orderBySize) { int allocatedMemoryInKB = 0; TypeDiffStatistics delta = GetDiffStatistics(typeInfos, typeInfos2, orderBySize); if (minCount > 0) { delta.TypeDiffs = delta.TypeDiffs.Where(x => Math.Abs(orderBySize ? x.InstanceCountDiff : x.AllocatedBytesDiff) > minCount).ToList(); } string fmt = "{0,-12:N0}\t{1,-17:N0}\t{2,-11:N0}\t{3,-11:N0}\t{4,-17:N0}\t{5,-18:N0}" + "\t{6,-14}\t{7,-15}\t{8}"; OutputStringWriter.FormatAndWriteHeader(fmt, $"Delta({DisplayUnit})", "Delta(Instances)", "Instances", "Instances2", $"Allocated({DisplayUnit})", $"Allocated2({DisplayUnit})", "AvgSize(Bytes)", "AvgSize2(Bytes)", "Type"); long unitDivisor = (long)DisplayUnit; if (topN > 0) { foreach (var diff in delta.TypeDiffs.Take(topN)) { if (diff.Name == FreeTypeName) { continue; } OutputStringWriter.FormatAndWrite(fmt, diff.AllocatedBytesDiff / unitDivisor, diff.InstanceCountDiff, diff?.Info.SafeCount(), diff?.Info2.SafeCount(), diff?.Info.TotalSize() / unitDivisor, diff?.Info2.TotalSize() / unitDivisor, diff?.Info?.AverageSizePerInstance, diff?.Info2?.AverageSizePerInstance, diff.Name); } } allocatedMemoryInKB = (int)(delta.DeltaBytes / (long)DisplayUnit.KB); OutputStringWriter.FormatAndWrite(fmt, delta.DeltaBytes / unitDivisor, delta.DeltaInstances, delta.Count, delta.Count2, delta.SizeInBytes / unitDivisor, delta.SizeInBytes2 / unitDivisor, "", "", ManagedHeapAllocated); long heap1Size = Heap.GetTotalHeapSize(); long heap2Size = Heap2.GetTotalHeapSize(); OutputStringWriter.FormatAndWrite(fmt, (heap2Size - heap1Size) / unitDivisor, 0, 0, 0, heap1Size / unitDivisor, heap2Size / unitDivisor, "", "", ManagedHeapSize); if (vmmap != null && vmmap2 != null && vmmap.HasValues && vmmap2.HasValues) { var diff = vmmap2 - vmmap; WriteVMMapDataDiff(GetSimpleDiffFormatter(fmt, DisplayUnit), vmmap, vmmap2, diff); OutputStringWriter.FormatAndWrite(fmt, (diff.AllocatedBytesWithoutManagedHeap + delta.DeltaBytes) / unitDivisor, "", "", "", (delta.SizeInBytes + vmmap.AllocatedBytesWithoutManagedHeap) / unitDivisor, (vmmap2.AllocatedBytesWithoutManagedHeap + delta.SizeInBytes2) / unitDivisor, "" , "", AllocatedTotal); // When VMMap data is present add the other memory types which usually leak as well also to the allocation number. allocatedMemoryInKB += (int)(diff.AllocatedBytesWithoutManagedHeap / (long)DisplayUnit.KB); } return(allocatedMemoryInKB); }
static TypeDiffStatistics GetDiffStatistics(List <TypeInfo> typeInfos, List <TypeInfo> typeInfos2, bool orderBySize) { HashSet <string> commonTypes = new HashSet <string>(typeInfos.Select(x => x.Name).Concat(typeInfos2.Select(x => x.Name))); var typeInfosDict = typeInfos.ToDictionary(x => x.Name); var typeInfosDict2 = typeInfos2.ToDictionary(x => x.Name); List <TypeInfoDiff> diffs = new List <TypeInfoDiff>(); foreach (var type in commonTypes) { typeInfosDict.TryGetValue(type, out TypeInfo info); typeInfosDict2.TryGetValue(type, out TypeInfo info2); diffs.Add(new TypeInfoDiff { AllocatedBytesDiff = info2.TotalSize() - info.TotalSize(), InstanceCountDiff = info2.SafeCount() - info.SafeCount(), Info = info, Info2 = info2, }); } // delta bytes and instances only show the allocated objects // on the heap and not sum free and allocated objects together diffs = diffs.Where(x => x.Name != FreeTypeName) .OrderByDescending(x => orderBySize ? Math.Abs(x.AllocatedBytesDiff) : Math.Abs(x.InstanceCountDiff)).ToList(); var deltaBytes = diffs.Sum(x => x.AllocatedBytesDiff); var deltaInstances = diffs.Sum(x => x.InstanceCountDiff); var count = (long)diffs.Sum(x => x?.Info.SafeCount()); var count2 = (long)diffs.Sum(x => x?.Info2.SafeCount()); var size = (long)diffs.Sum(x => x?.Info.TotalSize()); var size2 = (long)diffs.Sum(x => x?.Info2.TotalSize()); TypeDiffStatistics lret = new TypeDiffStatistics { TypeDiffs = diffs, Count = count, Count2 = count2, DeltaBytes = deltaBytes, DeltaInstances = deltaInstances, SizeInBytes = size, SizeInBytes2 = size2 }; return(lret); }