コード例 #1
0
ファイル: HeapRecording.cs プロジェクト: konlil/HeapProfiler
        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);
        }
コード例 #2
0
ファイル: DiffViewer.cs プロジェクト: kg/HeapProfiler
 public long GetBytesTotal(HeapSnapshotInfo item)
 {
     return (long)(item.BytesTotal);
 }
コード例 #3
0
ファイル: HeapRecording.cs プロジェクト: konlil/HeapProfiler
        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
            ));
        }
コード例 #4
0
ファイル: HeapRecording.cs プロジェクト: konlil/HeapProfiler
        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;
        }
コード例 #5
0
ファイル: MainWindow.cs プロジェクト: kg/HeapProfiler
        public long GetBytesTotal(HeapSnapshotInfo item)
        {
            FilteredHeapSnapshotInfo info = item;

            if (CurrentFilterData != null)
                if (!CurrentFilterData.TryGetValue(item, out info))
                    info = item;

            return (long)(info.BytesTotal);
        }
コード例 #6
0
ファイル: HeapViewer.cs プロジェクト: konlil/HeapProfiler
        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();
            }
        }
コード例 #7
0
ファイル: MainWindow.cs プロジェクト: kg/HeapProfiler
 public static long GetWorkingSet(HeapSnapshotInfo item)
 {
     return item.Memory.WorkingSet;
 }
コード例 #8
0
ファイル: MainWindow.cs プロジェクト: kg/HeapProfiler
        public long GetAllocationCount(HeapSnapshotInfo item)
        {
            FilteredHeapSnapshotInfo info = item;

            if (CurrentFilterData != null)
                if (!CurrentFilterData.TryGetValue(item, out info))
                    info = item;

            return (long)(info.AllocationCount);
        }
コード例 #9
0
ファイル: MainWindow.cs プロジェクト: kg/HeapProfiler
 public static long GetPagedMemory(HeapSnapshotInfo item)
 {
     return item.Memory.Paged;
 }
コード例 #10
0
ファイル: MainWindow.cs プロジェクト: kg/HeapProfiler
 public static long GetVirtualMemory(HeapSnapshotInfo item)
 {
     return item.Memory.Virtual;
 }
コード例 #11
0
ファイル: MainWindow.cs プロジェクト: kg/HeapProfiler
 public static long GetLargestOccupiedHeapBlock(HeapSnapshotInfo item)
 {
     return item.LargestOccupiedHeapBlock;
 }
コード例 #12
0
ファイル: MainWindow.cs プロジェクト: kg/HeapProfiler
 public static long GetHeapFragmentation(HeapSnapshotInfo item)
 {
     return (long)(item.HeapFragmentation * 10000);
 }
コード例 #13
0
ファイル: MainWindow.cs プロジェクト: kg/HeapProfiler
 public static long GetAverageOccupiedHeapBlockSize(HeapSnapshotInfo item)
 {
     return item.AverageOccupiedBlockSize;
 }
コード例 #14
0
ファイル: MainWindow.cs プロジェクト: kg/HeapProfiler
 public static long GetAverageFreeHeapBlockSize(HeapSnapshotInfo item)
 {
     return item.AverageFreeBlockSize;
 }
コード例 #15
0
        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
            ));
        }