protected IEnumerator<object> LoadSnapshotFromDatabase(HeapSnapshotInfo info) { var result = new HeapSnapshot(info); var fModules = Database.SnapshotModules.Get(info.Index); var fHeaps = Database.SnapshotHeaps.Get(info.Index); using (fModules) yield return fModules; var fModuleInfos = Database.Modules.Select(fModules.Result); using (fModuleInfos) yield return fModuleInfos; foreach (var module in fModuleInfos.Result) result.Modules.Add(module); using (fHeaps) yield return fHeaps; var heapIDs = from heap in fHeaps.Result select heap.HeapID; var fAllocations = Database.HeapAllocations.Select(heapIDs); using (fAllocations) yield return fAllocations; var allocations = SequenceUtils.ToDictionary(heapIDs, fAllocations.Result); var tracebackIDs = new HashSet<UInt32>(); foreach (var heapInfo in fHeaps.Result) { var theHeap = new HeapSnapshot.Heap(heapInfo); var allocationIds = allocations[heapInfo.HeapID]; theHeap.Allocations.Capacity = allocationIds.Length; var fRanges = Database.Allocations.Select(allocationIds); using (fRanges) yield return fRanges; yield return Future.RunInThread(() => SequenceUtils.Zip( allocationIds, fRanges.Result, (id, ranges) => { HeapSnapshot.AllocationRanges.Range range; if (ranges.Get(info.Index, out range)) { theHeap.Allocations.Add(new HeapSnapshot.Allocation( id, range.Size, range.Overhead, range.TracebackID )); tracebackIDs.Add(range.TracebackID); } } ) ); result.Heaps.Add(theHeap); } var fTracebacks = Database.FilteredTracebacks.CascadingSelect( new [] { Database.Tracebacks }, tracebackIDs ); using (fTracebacks) yield return fTracebacks; result.Tracebacks.ReplaceWith(fTracebacks.Result); yield return Result.New(result); }
public long GetBytesTotal(HeapSnapshotInfo item) { return (long)(item.BytesTotal); }
public IEnumerator<object> DiffSnapshots(HeapSnapshotInfo first, HeapSnapshotInfo last) { var moduleNames = new NameTable(StringComparer.Ordinal); var heapIds = new HashSet<UInt32>(); var functionNames = new NameTable(); var deltas = new List<DeltaInfo>(); var tracebacks = new Dictionary<UInt32, TracebackInfo>(); { var fModulesFirst = Database.SnapshotModules.Get(first.Index); var fModulesLast = Database.SnapshotModules.Get(last.Index); var fHeapsFirst = Database.SnapshotHeaps.Get(first.Index); var fHeapsLast = Database.SnapshotHeaps.Get(last.Index); yield return fModulesFirst; foreach (var moduleName in fModulesFirst.Result) moduleNames.Add(Path.GetFileNameWithoutExtension(moduleName)); yield return fHeapsFirst; heapIds.UnionWith(from heap in fHeapsFirst.Result select heap.HeapID); yield return fModulesLast; foreach (var moduleName in fModulesLast.Result) moduleNames.Add(Path.GetFileNameWithoutExtension(moduleName)); yield return fHeapsLast; heapIds.UnionWith(from heap in fHeapsLast.Result select heap.HeapID); } var allocationIds = new HashSet<UInt32>(); { var fAllocations = Database.HeapAllocations.Select(heapIds); using (fAllocations) yield return fAllocations; yield return Future.RunInThread(() => { foreach (var ids in fAllocations.Result) allocationIds.UnionWith(ids); }); } { var tracebackIds = new HashSet<UInt32>(); var oldCounts = new Dictionary<UInt32, int>(); var oldBytes = new Dictionary<UInt32, int>(); var newCounts = new Dictionary<UInt32, int>(); var newBytes = new Dictionary<UInt32, int>(); var deallocs = new Dictionary<UInt32, DeltaInfo>(); var allocs = new Dictionary<UInt32, DeltaInfo>(); var fAllocationRanges = Database.Allocations.Select(allocationIds); using (fAllocationRanges) yield return fAllocationRanges; yield return Future.RunInThread(() => { DeltaInfo delta; foreach (var item in fAllocationRanges.Result) { var ranges = item.Ranges.Array; for (int i = 0, c = item.Ranges.Count, o = item.Ranges.Offset; i < c; i++) { var range = ranges[i + o]; bool aliveAtStart = (range.First <= first.Index) && (range.Last > first.Index); bool aliveAtEnd = (range.First <= last.Index) && (range.Last > last.Index); bool allocatedInWindow = (range.First >= first.Index) && (range.First <= last.Index); bool deallocatedInWindow = (range.Last >= first.Index) && (range.Last <= last.Index); if (!aliveAtStart && !aliveAtEnd && !allocatedInWindow && !deallocatedInWindow) continue; if (aliveAtStart) { int value; if (!oldCounts.TryGetValue(range.TracebackID, out value)) value = 0; oldCounts[range.TracebackID] = value + 1; if (!oldBytes.TryGetValue(range.TracebackID, out value)) value = 0; oldBytes[range.TracebackID] = (int)(value + range.Size); } if (aliveAtEnd) { int value; if (!newCounts.TryGetValue(range.TracebackID, out value)) value = 0; newCounts[range.TracebackID] = value + 1; if (!newBytes.TryGetValue(range.TracebackID, out value)) value = 0; newBytes[range.TracebackID] = (int)(value + range.Size); } if (allocatedInWindow) { // allocation if (allocs.TryGetValue(range.TracebackID, out delta)) { delta.CountDelta += 1; delta.BytesDelta += (int)(range.Size); } else { allocs.Add(range.TracebackID, new DeltaInfo { BytesDelta = (int)(range.Size), CountDelta = 1, TracebackID = range.TracebackID, Traceback = null }); } tracebackIds.Add(range.TracebackID); } if (deallocatedInWindow) { // deallocation if (deallocs.TryGetValue(range.TracebackID, out delta)) { delta.CountDelta -= 1; delta.BytesDelta -= (int)(range.Size); } else { deallocs.Add(range.TracebackID, new DeltaInfo { BytesDelta = -(int)(range.Size), CountDelta = -1, TracebackID = range.TracebackID, Traceback = null }); } tracebackIds.Add(range.TracebackID); } } } foreach (var tracebackId in tracebackIds) { DeltaInfo alloc = null, dealloc = null; if (allocs.TryGetValue(tracebackId, out alloc) | deallocs.TryGetValue(tracebackId, out dealloc)) { int currentOldBytes, currentOldCount; int currentNewBytes, currentNewCount; oldBytes.TryGetValue(tracebackId, out currentOldBytes); oldCounts.TryGetValue(tracebackId, out currentOldCount); newBytes.TryGetValue(tracebackId, out currentNewBytes); newCounts.TryGetValue(tracebackId, out currentNewCount); if (alloc != null) { alloc.OldBytes = currentOldBytes; alloc.OldCount = currentOldCount; alloc.NewBytes = currentNewBytes; alloc.NewCount = currentNewCount; deltas.Add(alloc); } if (dealloc != null) { dealloc.OldBytes = currentOldBytes; dealloc.OldCount = currentOldCount; dealloc.NewBytes = currentNewBytes; dealloc.NewCount = currentNewCount; deltas.Add(dealloc); } } } }); var fTracebacks = Database.FilteredTracebacks.CascadingSelect( new [] { Database.Tracebacks }, tracebackIds ); using (fTracebacks) yield return fTracebacks; yield return ResolveTracebackSymbols( fTracebacks.Result, tracebacks, functionNames ); yield return Future.RunInThread(() => { foreach (var d in deltas) d.Traceback = tracebacks[d.TracebackID]; }); } yield return Future.RunInThread(() => deltas.Sort((lhs, rhs) => { var lhsBytes = lhs.BytesDelta; var rhsBytes = rhs.BytesDelta; return rhsBytes.CompareTo(lhsBytes); }) ); yield return Result.New(new HeapDiff( null, moduleNames, functionNames, deltas, tracebacks )); }
public Future<HeapSnapshot> GetSnapshot(HeapSnapshotInfo info) { var snapshot = info.Snapshot; if (snapshot != null) return new Future<HeapSnapshot>(snapshot); var f = new Future<HeapSnapshot>(); Scheduler.Start( f, new SchedulableGeneratorThunk(LoadSnapshotFromDatabase(info)), TaskExecutionPolicy.RunAsBackgroundTask ); return f; }
public long GetBytesTotal(HeapSnapshotInfo item) { FilteredHeapSnapshotInfo info = item; if (CurrentFilterData != null) if (!CurrentFilterData.TryGetValue(item, out info)) info = item; return (long)(info.BytesTotal); }
private IEnumerator<object> SetCurrentSnapshot(HeapSnapshotInfo info) { var oldSnapshot = Snapshot; if (oldSnapshot != null) oldSnapshot.Info.ReleaseStrongReference(); using (Finally.Do(() => { UseWaitCursor = false; })) { var fSnapshot = Instance.GetSnapshot(info); yield return fSnapshot; Snapshot = fSnapshot.Result; RefreshHeap(); } }
public static long GetWorkingSet(HeapSnapshotInfo item) { return item.Memory.WorkingSet; }
public long GetAllocationCount(HeapSnapshotInfo item) { FilteredHeapSnapshotInfo info = item; if (CurrentFilterData != null) if (!CurrentFilterData.TryGetValue(item, out info)) info = item; return (long)(info.AllocationCount); }
public static long GetPagedMemory(HeapSnapshotInfo item) { return item.Memory.Paged; }
public static long GetVirtualMemory(HeapSnapshotInfo item) { return item.Memory.Virtual; }
public static long GetLargestOccupiedHeapBlock(HeapSnapshotInfo item) { return item.LargestOccupiedHeapBlock; }
public static long GetHeapFragmentation(HeapSnapshotInfo item) { return (long)(item.HeapFragmentation * 10000); }
public static long GetAverageOccupiedHeapBlockSize(HeapSnapshotInfo item) { return item.AverageOccupiedBlockSize; }
public static long GetAverageFreeHeapBlockSize(HeapSnapshotInfo item) { return item.AverageFreeBlockSize; }
public IEnumerator<object> DiffSnapshots(HeapSnapshotInfo first, HeapSnapshotInfo last) { var moduleNames = new NameTable(StringComparer.Ordinal); var heapIds = new HashSet<UInt32>(); var functionNames = new NameTable(); var deltas = new List<DeltaInfo>(); var tracebacks = new Dictionary<UInt32, TracebackInfo>(); { var fModulesFirst = Database.SnapshotModules.Get(first.Index); var fModulesLast = Database.SnapshotModules.Get(last.Index); var fHeapsFirst = Database.SnapshotHeaps.Get(first.Index); var fHeapsLast = Database.SnapshotHeaps.Get(last.Index); yield return fModulesFirst; foreach (var moduleName in fModulesFirst.Result) moduleNames.Add(Path.GetFileNameWithoutExtension(moduleName)); yield return fHeapsFirst; heapIds.UnionWith(from heap in fHeapsFirst.Result select heap.HeapID); yield return fModulesLast; foreach (var moduleName in fModulesLast.Result) moduleNames.Add(Path.GetFileNameWithoutExtension(moduleName)); yield return fHeapsLast; heapIds.UnionWith(from heap in fHeapsLast.Result select heap.HeapID); } var allocationIds = new HashSet<UInt32>(); { var fAllocations = Database.HeapAllocations.Select(heapIds); using (fAllocations) yield return fAllocations; yield return Future.RunInThread(() => { foreach (var ids in fAllocations.Result) allocationIds.UnionWith(ids); }); } { var tracebackIds = new HashSet<UInt32>(); var deallocs = new Dictionary<UInt32, DeltaInfo>(); var allocs = new Dictionary<UInt32, DeltaInfo>(); var fAllocationRanges = Database.Allocations.Select(allocationIds); using (fAllocationRanges) yield return fAllocationRanges; yield return Future.RunInThread(() => { DeltaInfo delta; foreach (var item in fAllocationRanges.Result) { var ranges = item.Ranges.Array; for (int i = 0, c = item.Ranges.Count, o = item.Ranges.Offset; i < c; i++) { var range = ranges[i + o]; if ((range.First <= first.Index) && (range.Last >= first.Index) && (range.Last < last.Index) ) { // deallocation if (deallocs.TryGetValue(range.TracebackID, out delta)) { delta.CountDelta += 1; delta.BytesDelta += (int)(range.Size + range.Overhead); delta.OldCount += 1; delta.OldBytes += (int)(range.Size + range.Overhead); } else { deallocs.Add(range.TracebackID, new DeltaInfo { Added = false, BytesDelta = (int)(range.Size + range.Overhead), CountDelta = 1, NewBytes = 0, NewCount = 0, OldBytes = (int)(range.Size + range.Overhead), OldCount = 1, TracebackID = range.TracebackID, Traceback = null }); } tracebackIds.Add(range.TracebackID); } else if ( (range.First <= last.Index) && (range.First > first.Index) && (range.Last >= last.Index) ) { // allocation if (allocs.TryGetValue(range.TracebackID, out delta)) { delta.CountDelta += 1; delta.BytesDelta += (int)(range.Size + range.Overhead); delta.NewCount += 1; delta.NewBytes += (int)(range.Size + range.Overhead); } else { allocs.Add(range.TracebackID, new DeltaInfo { Added = true, BytesDelta = (int)(range.Size + range.Overhead), CountDelta = 1, NewBytes = (int)(range.Size + range.Overhead), NewCount = 1, OldBytes = 0, OldCount = 0, TracebackID = range.TracebackID, Traceback = null }); } tracebackIds.Add(range.TracebackID); } } } foreach (var tracebackId in tracebackIds) { if (allocs.TryGetValue(tracebackId, out delta)) { DeltaInfo dealloc; if (deallocs.TryGetValue(tracebackId, out dealloc)) { delta.OldBytes = dealloc.OldBytes; delta.OldCount = dealloc.OldCount; delta.BytesDelta = Math.Abs(delta.NewBytes - delta.OldBytes); delta.CountDelta = Math.Abs(delta.NewCount - delta.OldCount.Value); if (delta.NewBytes < delta.OldBytes) delta.Added = false; } if (delta.BytesDelta != 0) deltas.Add(delta); } else if (deallocs.TryGetValue(tracebackId, out delta)) { if (delta.BytesDelta != 0) deltas.Add(delta); } } }); var fTracebacks = Database.Tracebacks.Select(tracebackIds); using (fTracebacks) yield return fTracebacks; Dictionary<UInt32, TracebackFrame> frameSymbols; { var rawFrames = new HashSet<UInt32>(); yield return Future.RunInThread(() => { foreach (var traceback in fTracebacks.Result) foreach (var rawFrame in traceback) rawFrames.Add(rawFrame); }); var fSymbols = Database.SymbolCache.Select(rawFrames); using (fSymbols) yield return fSymbols; var fSymbolDict = Future.RunInThread(() => SequenceUtils.ToDictionary(rawFrames, fSymbols.Result) ); yield return fSymbolDict; frameSymbols = fSymbolDict.Result; } yield return Future.RunInThread(() => { foreach (var tf in frameSymbols.Values) { if (tf.Function != null) functionNames.Add(tf.Function); } foreach (var traceback in fTracebacks.Result) { tracebacks[traceback.ID] = ConstructTracebackInfo( traceback.ID, traceback.Frames, frameSymbols ); } foreach (var d in deltas) d.Traceback = tracebacks[d.TracebackID]; }); } yield return Future.RunInThread(() => deltas.Sort((lhs, rhs) => { var lhsBytes = (lhs.Added ? 1 : -1) * lhs.BytesDelta; var rhsBytes = (rhs.Added ? 1 : -1) * rhs.BytesDelta; return rhsBytes.CompareTo(lhsBytes); }) ); yield return Result.New(new HeapDiff( null, moduleNames, functionNames, deltas, tracebacks )); }