Ejemplo n.º 1
0
        protected IEnumerator <object> FinishShowingTooltip(
            Point mouseLocation,
            HeapSnapshot.Heap heap,
            HeapSnapshot.Allocation allocation,
            HeapSnapshot.Traceback rawTraceback
            )
        {
            var uniqueRawFrames = rawTraceback.Frames.AsEnumerable().Distinct();

            var fSymbols = Instance.Database.SymbolCache.Select(uniqueRawFrames);

            using (fSymbols)
                yield return(fSymbols);

            var symbolDict = SequenceUtils.ToDictionary(
                uniqueRawFrames, fSymbols.Result
                );

            var tracebackInfo = HeapRecording.ConstructTracebackInfo(
                rawTraceback.ID, rawTraceback.Frames, symbolDict
                );

            var renderParams = new DeltaInfo.RenderParams {
                BackgroundBrush = new SolidBrush(SystemColors.Info),
                BackgroundColor = SystemColors.Info,
                TextBrush       = new SolidBrush(SystemColors.InfoText),
                IsExpanded      = true,
                IsSelected      = false,
                Font            = Font,
                ShadeBrush      = new SolidBrush(Color.FromArgb(31, 0, 0, 0)),
                StringFormat    = CustomTooltip.GetDefaultStringFormat()
            };

            var content = new HeapSnapshot.AllocationTooltipContent(
                ref allocation, ref tracebackInfo, ref renderParams
                )
            {
                Location = mouseLocation,
                Font     = Font
            };

            using (var g = CreateGraphics())
                CustomTooltip.FitContentOnScreen(
                    g, content,
                    ref content.RenderParams.Font,
                    ref content.Location, ref content.Size
                    );

            Tooltip.SetContent(content);
        }
Ejemplo n.º 2
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
                                        )));
        }
Ejemplo n.º 3
0
        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(
                from moduleName in fModules.Result select moduleName
                );

            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.Tracebacks.Select(tracebackIDs);

            using (fTracebacks)
                yield return(fTracebacks);

            yield return(Future.RunInThread(() => {
                foreach (var traceback in fTracebacks.Result)
                {
                    result.Tracebacks.Add(traceback);
                }
            }));

            yield return(Result.New(result));
        }