public static HeapSnapshot Diff(HeapSnapshot baseline, HeapSnapshot current) { var result = new HeapSnapshot(); var baselineTypes = new HashSet <string>(baseline.SizeByType.Keys); var currentTypes = new HashSet <string>(current.SizeByType.Keys); baselineTypes.IntersectWith(currentTypes); foreach (var type in baselineTypes) // In both baseline and current { result.SizeByType.Add(type, current.SizeByType[type] - baseline.SizeByType[type]); result.CountByType.Add(type, current.CountByType[type] - baseline.CountByType[type]); } baselineTypes = new HashSet <string>(baseline.SizeByType.Keys); baselineTypes.ExceptWith(currentTypes); foreach (var type in baselineTypes) // Only in baseline { result.SizeByType.Add(type, -baseline.SizeByType[type]); result.CountByType.Add(type, -baseline.CountByType[type]); } baselineTypes = new HashSet <string>(baseline.SizeByType.Keys); currentTypes.ExceptWith(baselineTypes); foreach (var type in currentTypes) // Only in current { result.SizeByType.Add(type, +current.SizeByType[type]); result.CountByType.Add(type, +current.CountByType[type]); } return(result); }
protected override void OnIntensiveSamplingStart() { var snapshots = new List <HeapSnapshot>(); for (int i = 0; i < SnapshotCount; ++i) { GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); using (var target = DataTarget.AttachToProcess(Process.GetCurrentProcess().Id, 1000, AttachFlag.Passive)) { var runtime = target.ClrVersions[0].CreateRuntime(); snapshots.Add(new HeapSnapshot(runtime.Heap, TopTypes)); Thread.Sleep(SnapshotInterval); } } for (int i = 0; i < SnapshotCount; ++i) { for (int j = i + 1; j < SnapshotCount; ++j) { var diff = HeapSnapshot.Diff(snapshots[i], snapshots[j]); WriteTraceLine($"Diff between snapshot {i} (baseline) and snapshot {j}:"); foreach (var typeSize in diff.SizeByType.OrderBy(v => v.Value)) // Biggest offenders printed last { WriteTraceLine($" {typeSize.Key,10} {typeSize.Value,8} {diff.CountByType[typeSize.Key],8}"); } } } }