using System; using System.Collections.Generic; namespace Tracing { public class ProcessAllocations { private readonly int _pid; private readonly Dictionary _allocations; private readonly Dictionary _perThreadLastAllocation; public ProcessAllocations(int pid) { _pid = pid; _allocations = new Dictionary(); _perThreadLastAllocation = new Dictionary(); } public int Pid => _pid; public AllocationInfo GetAllocations(string typeName) { return (_allocations.TryGetValue(typeName, out var info)) ? info : null; } public IEnumerable GetAllAllocations() { return _allocations.Values; } public AllocationInfo AddAllocation(int threadID, ulong size, ulong count, string typeName) { if (!_allocations.TryGetValue(typeName, out var info)) { info = new AllocationInfo(typeName); _allocations[typeName] = info; } info.AddAllocation(size, count); // the last allocation is still here without the corresponding stack if (_perThreadLastAllocation.TryGetValue(threadID, out var lastAlloc)) { Console.WriteLine("no stack for the last allocation"); } // keep track of the allocation for the given thread // --> will be used when the corresponding call stack event will be received _perThreadLastAllocation[threadID] = info; return info; } public void AddStack(int threadID, AddressStack stack) { if (_perThreadLastAllocation.TryGetValue(threadID, out var lastAlloc)) { lastAlloc.AddStack(stack); _perThreadLastAllocation.Remove(threadID); return; } //Console.WriteLine("no last allocation for the stack event"); } } public class AllocationInfo { private readonly string _typeName; private ulong _size; private ulong _count; private List _stacks; internal AllocationInfo(string typeName) { _typeName = typeName; _stacks = new List(); } public string TypeName => _typeName; public ulong Count => _count; public ulong Size => _size; public IReadOnlyList Stacks => _stacks; internal void AddAllocation(ulong size, ulong count) { _count += count; _size += size; } internal void AddStack(AddressStack stack) { var info = GetInfo(stack); if (info == null) { info = new StackInfo(stack); _stacks.Add(info); } info.Count++; } private StackInfo GetInfo(AddressStack stack) { for (int i = 0; i < _stacks.Count; i++) { var info = _stacks[i]; if (stack.Equals(info.Stack)) return info; } return null; } } public class StackInfo { private readonly AddressStack _stack; public ulong Count; internal StackInfo(AddressStack stack) { Count = 0; _stack = stack; } public AddressStack Stack => _stack; } }