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}");
                    }
                }
            }
        }