Пример #1
0
        /// <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);
        }
Пример #2
0
        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);
        }