示例#1
0
        private void PrintDiff(int topN, StringAnalysisResult res, StringAnalysisResult res2)
        {
            var top  = res.StringCounts.OrderByDescending(kvp => kvp.Value.InstanceCount).Take(topN).ToDictionary(x => x.Key, x => x.Value);
            var top2 = res2.StringCounts.OrderByDescending(kvp => kvp.Value.InstanceCount).Take(topN).ToDictionary(x => x.Key, x => x.Value);

            HashSet <string>  uniqueStringValues = new HashSet <string>(top.Select(x => x.Key).Concat(top2.Select(x => x.Key)).ToArray());
            List <StringDiff> diffs = new List <StringDiff>();

            foreach (var stringValue in uniqueStringValues)
            {
                ObjectStatistics stat  = null;
                ObjectStatistics stat2 = null;
                top.TryGetValue(stringValue, out stat);
                top2.TryGetValue(stringValue, out stat2);
                diffs.Add(new StringDiff
                {
                    DiffInBytes       = (stat2 != null ? stat2.AllocatedInBytes : 0) - (stat != null ? stat.AllocatedInBytes : 0),
                    InstanceDiffCount = (stat2 != null ? stat2.InstanceCount : 0) - (stat != null ? stat.InstanceCount : 0),
                    Stat  = stat,
                    Stat2 = stat2,
                    Value = stringValue
                });
            }

            var sortedDiffs = diffs.OrderByDescending(x => Math.Abs(x.DiffInBytes)).ToArray();

            Console.WriteLine("String Allocation Diff Statistics");
            string fmtString = "{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}";

            OutputStringWriter.FormatAndWrite(fmtString, $"Delta({DisplayUnit})", "Delta(Instances)", "Instances", "Instances2", $"Allocated({DisplayUnit})", $"Allocated2({DisplayUnit})", "Value");

            long displayUnitDiv = (long)DisplayUnit;

            foreach (var diff in sortedDiffs)
            {
                OutputStringWriter.FormatAndWrite(fmtString, diff.DiffInBytes / displayUnitDiv, diff.InstanceDiffCount, diff?.Stat?.InstanceCount, diff?.Stat2?.InstanceCount, diff?.Stat?.AllocatedInBytes / displayUnitDiv, diff?.Stat2?.AllocatedInBytes / displayUnitDiv, GetShortString(diff.Value));
            }

            var deltaCount = res2.StringObjectCount - res.StringObjectCount;
            var deltaWaste = res2.StringWasteInBytes - res.StringWasteInBytes;
            var deltaBytes = res2.StringsAllocatedInBytes - res.StringsAllocatedInBytes;

            OutputStringWriter.FormatAndWrite(fmtString, deltaBytes / displayUnitDiv, deltaCount, res.StringObjectCount, res2.StringObjectCount,
                                              res.StringsAllocatedInBytes / displayUnitDiv, res2.StringsAllocatedInBytes / displayUnitDiv, "Strings(Total)");
        }
示例#2
0
        static StringAnalysisResult Analyze(ClrHeap heap, bool bLiveOnly)
        {
            var stringUsages = new Dictionary <string, ObjectStatistics>();

            foreach (var instance in GetObjectAddresses(heap, bLiveOnly))
            {
                var type = heap.GetObjectType(instance);
                if (type != null && type.IsString)
                {
                    var value = (string)type.GetValue(instance);
                    ObjectStatistics countAndSize = null;
                    if (stringUsages.TryGetValue(value, out countAndSize))
                    {
                        countAndSize.InstanceCount++;
                    }
                    else
                    {
                        var size = type.GetSize(instance);
                        stringUsages[value] = new ObjectStatistics {
                            SizePerInstance = (long)size, InstanceCount = 1, SampleAddress = instance
                        };
                    }
                }
            }

            var stringWasteInBytes    = stringUsages.Values.Sum(o => (long)o.SizePerInstance * (long)(o.InstanceCount - 1));
            var stringObjectCount     = stringUsages.Values.Sum(o => (long)o.InstanceCount);
            var stringsAllocatedBytes = stringUsages.Values.Sum(o => (long)o.AllocatedInBytes);

            return(new StringAnalysisResult
            {
                StringCounts = stringUsages,
                StringWasteInBytes = stringWasteInBytes,
                StringObjectCount = stringObjectCount,
                StringsAllocatedInBytes = stringsAllocatedBytes
            });
        }