// Process a trace and create a summary. static SnapshotSummary GetAllocSummary(ITraceProcessor trace) { var pendingSnapshotData = trace.UseHeapSnapshots(); var pendingSymbols = trace.UseSymbols(); trace.Process(); var snapshotData = pendingSnapshotData.Result; var symbols = pendingSymbols.Result; symbols.LoadSymbolsAsync(new SymCachePath(@"c:\symcache")).GetAwaiter().GetResult(); if (snapshotData.Snapshots.Count != 1) { Console.Error.WriteLine("Trace must contain exactly one heap snapshot - actually contained {0}.", snapshotData.Snapshots.Count); return(new SnapshotSummary(null, 0)); } // Scan through all of the allocations and collect them by // SnapshotUniqueStackId (which corresponds to Stack Ref#), // accumulating the bytes allocated, allocation count, and the // stack. var allocsByStackId = new Dictionary <ulong, AllocDetails>(); foreach (IHeapAllocation row in snapshotData.Snapshots[0].Allocations) { allocsByStackId.TryGetValue(row.SnapshotUniqueStackId, out AllocDetails value); value.Stack = row.Stack; value.Size += row.Size; value.Count += 1; allocsByStackId[row.SnapshotUniqueStackId] = value; } // Count how many allocations each stack frame is part of. // RtlThreadStart will presumably be near the top, along with // RtlpAllocateHeapInternal, but some clues may be found. var hotStackFrames = new Dictionary <string, long>(); foreach (var data in allocsByStackId.Values) { foreach (var entry in data.Stack) { var analyzerString = entry.GetAnalyzerString(); hotStackFrames.TryGetValue(analyzerString, out long count); count += data.Count; hotStackFrames[analyzerString] = count; } } var result = new SnapshotSummary(allocsByStackId, snapshotData.Snapshots[0].ProcessId); // Create a summary of the alloc counts and byte counts. var totalAllocBytes = DataSize.Zero; long totalAllocCount = 0; foreach (var data in allocsByStackId.Values) { totalAllocBytes += data.Size; totalAllocCount += data.Count; } result.hotStackFrames_ = hotStackFrames; result.totalBytes_ = totalAllocBytes; result.allocCount_ = totalAllocCount; return(result); }