Esempio n. 1
0
        public static void ParseSnapshot(List <FCallStackAllocationInfo> CallStackList, string FilterText)
        {
            // Progress bar
            long ProgressInterval   = CallStackList.Count / 20;
            long NextProgressUpdate = ProgressInterval;
            int  CallStackCurrent   = 0;

            OwnerWindow.ToolStripProgressBar.Value   = 0;
            OwnerWindow.ToolStripProgressBar.Visible = true;

            OwnerWindow.UpdateStatus("Updating histogram view for " + OwnerWindow.CurrentFilename);

            List <ClassGroup> CallStackGroups = OwnerWindow.Options.ClassGroups;

            List <FHistogramBar>[] Bars = new List <FHistogramBar> [NUM_MEMORY_BANKS];

            for (int BankIndex = 0; BankIndex < Bars.Length; BankIndex++)
            {
                Bars[BankIndex] = new List <FHistogramBar>();

                // The first bar in each column is for callstacks unmatched by any pattern.
                Bars[BankIndex].Add(new FHistogramBar("Other", Color.White));

                // Add all groups to all memory bank columns.
                foreach (ClassGroup CallStackGroup in CallStackGroups)
                {
                    var Bar = new FHistogramBar(CallStackGroup);
                    Bar.BeginBatchAddition();
                    Bars[BankIndex].Add(Bar);
                }
            }

            using (FScopedLogTimer ParseTiming = new FScopedLogTimer("HistogramParser.ParseSnapshot"))
            {
                long Size  = 0;
                int  Count = 0;

                bool bFilterIn = OwnerWindow.IsFilteringIn();

                var FilteredCallstackList = new List <FCallStackAllocationInfo>(CallStackList.Count);
                foreach (var AllocationInfo in CallStackList)
                {
                    var FilteredAllocationInfo = AllocationInfo.GetAllocationInfoForTags(OwnerWindow.GetTagsFilter(), bFilterIn);
                    if (FilteredAllocationInfo.TotalCount != 0)
                    {
                        FilteredCallstackList.Add(FilteredAllocationInfo);
                    }
                }

                foreach (FCallStackAllocationInfo AllocationInfo in FilteredCallstackList)
                {
                    // Update progress bar.
                    if (CallStackCurrent >= NextProgressUpdate)
                    {
                        OwnerWindow.ToolStripProgressBar.PerformStep();
                        NextProgressUpdate += ProgressInterval;
                        Debug.WriteLine("FHistogramParser.ParseSnapshot " + OwnerWindow.ToolStripProgressBar.Value + "/20");
                    }
                    CallStackCurrent++;

                    FCallStack OriginalCallStack = FStreamInfo.GlobalInstance.CallStackArray[AllocationInfo.CallStackIndex];
                    if (OriginalCallStack.RunFilters(FilterText, CallStackGroups, bFilterIn, OwnerWindow.SelectedMemoryPool))
                    {
                        bool bFound = false;
                        int  Column = FMemoryPoolInfo.GetMemoryPoolHistogramColumn(OriginalCallStack.MemoryPool);
                        if (Column == -1)
                        {
                            // If the callstack is in multiple pools, just put it in the first bank.
                            // The user has already been warned about multi-pool callstacks.
                            Column = 0;
                        }

                        for (int GroupIndex = 0; GroupIndex < CallStackGroups.Count; GroupIndex++)
                        {
                            foreach (CallStackPattern CallStackPatternIt in CallStackGroups[GroupIndex].CallStackPatterns)
                            {
                                if (CallStackPatternIt.ContainsCallStack(FStreamInfo.GlobalInstance.CallStackArray[AllocationInfo.CallStackIndex]))
                                {
                                    Bars[Column][GroupIndex + 1].AddAllocation(AllocationInfo);
                                    bFound = true;
                                    goto HackyBreakAll;
                                }
                            }
                        }
HackyBreakAll:

                        if (!bFound)
                        {
                            // No pattern matched this callstack, so add it to the Other bar
                            Bars[Column][0].AddAllocation(AllocationInfo);
                        }
                    }

                    Size  += AllocationInfo.TotalSize;
                    Count += AllocationInfo.TotalCount;
                }
            }

            // End the update batch and allow things to sort
            for (int BankIndex = 0; BankIndex < Bars.Length; BankIndex++)
            {
                foreach (ClassGroup CallStackGroup in CallStackGroups)
                {
                    foreach (var Bar in Bars[BankIndex])
                    {
                        Bar.EndBatchAddition();
                    }
                }
            }

            OwnerWindow.ToolStripProgressBar.Visible = false;
            HistogramBars = Bars;

            // Select first valid histogram bar.
            SelectFirstValidHistogramBar();
        }
        public static void ParseSnapshot(ListViewEx ExclusiveListView, List <FCallStackAllocationInfo> CallStackList, bool bShouldSortBySize, string FilterText)
        {
            const int MaximumEntries = 400;

            // Progress bar.
            long ProgressInterval   = MaximumEntries / 20;
            long NextProgressUpdate = ProgressInterval;
            int  CallStackCurrent   = 0;

            OwnerWindow.ToolStripProgressBar.Value   = 0;
            OwnerWindow.ToolStripProgressBar.Visible = true;

            OwnerWindow.UpdateStatus("Updating exclusive list view for " + OwnerWindow.CurrentFilename);

            ExclusiveListView.BeginUpdate();

            ExclusiveListView.ListViewItemSorter = null;             // clear this to avoid a Sort for each call to Add

            bool bFilterIn = OwnerWindow.IsFilteringIn();

            using (FScopedLogTimer ParseTiming = new FScopedLogTimer("FExclusiveListViewParser.ParseSnapshot"))
            {
                var FilteredCallstackList = new List <FCallStackAllocationInfo>(CallStackList.Count);
                foreach (var AllocationInfo in CallStackList)
                {
                    var FilteredAllocationInfo = AllocationInfo.GetAllocationInfoForTags(OwnerWindow.GetTagsFilter(), bFilterIn);
                    if (FilteredAllocationInfo.TotalCount != 0)
                    {
                        FilteredCallstackList.Add(FilteredAllocationInfo);
                    }
                }

                // Sort based on passed in metric.
                if (bShouldSortBySize)
                {
                    FilteredCallstackList.Sort(CompareAbsSize);
                }
                else
                {
                    FilteredCallstackList.Sort(CompareCount);
                }

                // Figure out total size and count for percentages.
                long TotalSize  = 0;
                long TotalCount = 0;
                foreach (FCallStackAllocationInfo AllocationInfo in FilteredCallstackList)
                {
                    // Apply optional filter.
                    if (FStreamInfo.GlobalInstance.CallStackArray[AllocationInfo.CallStackIndex].RunFilters(FilterText, OwnerWindow.Options.ClassGroups, bFilterIn, OwnerWindow.SelectedMemoryPool))
                    {
                        TotalSize  += AllocationInfo.TotalSize;
                        TotalCount += AllocationInfo.TotalCount;
                    }
                }

                // Clear out existing entries and add top 400.
                ExclusiveListView.Items.Clear();
                for (int CallStackIndex = 0; CallStackIndex < FilteredCallstackList.Count && ExclusiveListView.Items.Count <= MaximumEntries; CallStackIndex++)
                {
                    // Update progress bar.
                    if (CallStackCurrent >= NextProgressUpdate)
                    {
                        OwnerWindow.ToolStripProgressBar.PerformStep();
                        NextProgressUpdate += ProgressInterval;
                        Debug.WriteLine("FExclusiveListViewParser.ParseSnapshot " + OwnerWindow.ToolStripProgressBar.Value + "/20");
                    }
                    CallStackCurrent++;

                    FCallStackAllocationInfo AllocationInfo = FilteredCallstackList[CallStackIndex];

                    // Apply optional filter.
                    FCallStack CallStack = FStreamInfo.GlobalInstance.CallStackArray[AllocationInfo.CallStackIndex];
                    if (CallStack.RunFilters(FilterText, OwnerWindow.Options.ClassGroups, bFilterIn, OwnerWindow.SelectedMemoryPool))
                    {
                        string FunctionName = "";
                        int    FirstStackFrameIndex;
                        if (OwnerWindow.ContainersSplitButton.Text == " Show Containers")
                        {
                            FirstStackFrameIndex = CallStack.AddressIndices.Count - 1;
                        }
                        else
                        {
                            FirstStackFrameIndex = CallStack.FirstNonContainer;
                        }

                        do
                        {
                            FCallStackAddress Address = FStreamInfo.GlobalInstance.CallStackAddressArray[CallStack.AddressIndices[FirstStackFrameIndex]];
                            FunctionName = FStreamInfo.GlobalInstance.NameArray[Address.FunctionIndex];

                            FirstStackFrameIndex--;
                        }while(UnhelpfulCallSites.Contains(FunctionName) && FirstStackFrameIndex > 0);

                        var AllocationSize  = AllocationInfo.TotalSize;
                        var AllocationCount = AllocationInfo.TotalCount;

                        string SizeInKByte  = String.Format("{0:0}", ( float )AllocationSize / 1024).PadLeft(10, ' ');
                        string SizePercent  = String.Format("{0:0.00}", ( float )AllocationSize / TotalSize * 100).PadLeft(10, ' ');
                        string Count        = String.Format("{0:0}", AllocationCount).PadLeft(10, ' ');
                        string CountPercent = String.Format("{0:0.00}", ( float )AllocationCount / TotalCount * 100).PadLeft(10, ' ');
                        string GroupName    = (CallStack.Group != null) ? CallStack.Group.Name : "Ungrouped";

                        string[] Row = new string[]
                        {
                            SizeInKByte,
                            SizePercent,
                            Count,
                            CountPercent,
                            GroupName,
                            FunctionName
                        };

                        ListViewItem Item = new ListViewItem(Row);
                        Item.Tag = AllocationInfo;
                        ExclusiveListView.Items.Add(Item);
                    }
                }
            }

            var ColumnSorter = new MainWindow.FColumnSorter();

            ColumnSorter.ColumnSortModeAscending = false;
            ColumnSorter.ColumnToSortBy          = 0;
            ExclusiveListView.ListViewItemSorter = ColumnSorter;             // Assignment automatically calls Sort

            ExclusiveListView.SetSortArrow(ColumnSorter.ColumnToSortBy, ColumnSorter.ColumnSortModeAscending);
            ExclusiveListView.EndUpdate();

            OwnerWindow.ToolStripProgressBar.Visible = false;
        }
        public static void ParseSnapshot(TreeView CallGraphTreeView, List <FCallStackAllocationInfo> CallStackList, bool bShouldSortBySize, string FilterText, bool bInvertCallStacks)
        {
            // Progress bar.
            OwnerWindow.ToolStripProgressBar.Value   = 0;
            OwnerWindow.ToolStripProgressBar.Visible = true;
            long ProgressInterval   = CallStackList.Count / 20;
            long NextProgressUpdate = ProgressInterval;
            int  CallStackCurrent   = 0;

            OwnerWindow.UpdateStatus("Updating call graph for " + OwnerWindow.CurrentFilename);

            CallGraphTreeView.BeginUpdate();

            // Clear out existing nodes and add two root nodes. One for regular call stacks and one for truncated ones.
            CallGraphTreeView.Nodes.Clear();
            TreeNode RegularNode   = new TreeNode("Full Callstacks");
            TreeNode TruncatedNode = new TreeNode("Truncated Callstacks");

            CallGraphTreeView.Nodes.Add(RegularNode);
            CallGraphTreeView.Nodes.Add(TruncatedNode);

            using (FScopedLogTimer ParseTiming = new FScopedLogTimer("FCallGraphTreeViewParser.ParseSnapshot"))
            {
                // Iterate over all call graph paths and add them to the graph.
                foreach (FCallStackAllocationInfo AllocationInfo in CallStackList)
                {
                    // Update progress bar.
                    if (CallStackCurrent >= NextProgressUpdate)
                    {
                        OwnerWindow.ToolStripProgressBar.PerformStep();
                        NextProgressUpdate += ProgressInterval;
                        Debug.WriteLine("FCallGraphTreeViewParser.ParseSnapshot " + OwnerWindow.ToolStripProgressBar.Value + "/20");
                    }
                    CallStackCurrent++;

                    // Add this call graph to the tree view.
                    FCallStack CallStack = FStreamInfo.GlobalInstance.CallStackArray[AllocationInfo.CallStackIndex];
                    // Split the tree into full and truncated callstacks.
                    TreeNode RootNode = CallStack.bIsTruncated ? TruncatedNode : RegularNode;
                    // Don't bother with callstacks that don't have a contribution.
                    if (((AllocationInfo.Count != 0) || (AllocationInfo.Size != 0))
                        // Apply filter based on text representation of address.
                        && CallStack.RunFilters(FilterText, OwnerWindow.Options.ClassGroups, OwnerWindow.IsFilteringIn(), OwnerWindow.SelectedMemoryPool))
                    {
                        // Add call stack to proper part of graph.
                        AddCallStackToGraph(RootNode, CallStack, AllocationInfo, ParentFunctionIndex, bInvertCallStacks);
                    }
                }
            }

            // Update the node text by prepending memory usage and allocation count.
            UpdateNodeText(RegularNode);
            UpdateNodeText(TruncatedNode);

            // Last but not least, set the node sorter property to sort nodes.
            if (bShouldSortBySize)
            {
                CallGraphTreeView.TreeViewNodeSorter = new FNodeSizeSorter();
            }
            else
            {
                CallGraphTreeView.TreeViewNodeSorter = new FNodeCountSorter();
            }

            CallGraphTreeView.EndUpdate();

            OwnerWindow.ToolStripProgressBar.Visible = false;
        }
        public static void ParseSnapshot(TreeView CallGraphTreeView, List <FCallStackAllocationInfo> CallStackList, bool bShouldSortBySize, string FilterText, bool bInvertCallStacks)
        {
            // Progress bar.
            OwnerWindow.ToolStripProgressBar.Value   = 0;
            OwnerWindow.ToolStripProgressBar.Visible = true;
            long ProgressInterval   = CallStackList.Count / 20;
            long NextProgressUpdate = ProgressInterval;
            int  CallStackCurrent   = 0;

            OwnerWindow.UpdateStatus("Updating call graph for " + OwnerWindow.CurrentFilename);

            CallGraphTreeView.BeginUpdate();

            CallGraphTreeView.TreeViewNodeSorter = null;             // clear this to avoid a Sort for each call to Add

            Debug.WriteLine("FCallGraphTreeViewParser.ParseSnapshot - Building call graph tree for " + OwnerWindow.CurrentFilename);

            var TruncatedNode = new FCallGraphNode("Truncated Callstacks");
            var RegularNode   = new FCallGraphNode("Full Callstacks");

            bool bFilterIn = OwnerWindow.IsFilteringIn();

            using (FScopedLogTimer ParseTiming = new FScopedLogTimer("FCallGraphTreeViewParser.ParseSnapshot"))
            {
                var FilteredCallstackList = new List <FCallStackAllocationInfo>(CallStackList.Count);
                foreach (var AllocationInfo in CallStackList)
                {
                    var FilteredAllocationInfo = AllocationInfo.GetAllocationInfoForTags(OwnerWindow.GetTagsFilter(), bFilterIn);
                    if (FilteredAllocationInfo.TotalCount != 0)
                    {
                        FilteredCallstackList.Add(FilteredAllocationInfo);
                    }
                }

                // Iterate over all call graph paths and add them to the graph.
                foreach (FCallStackAllocationInfo AllocationInfo in FilteredCallstackList)
                {
                    // Update progress bar.
                    if (CallStackCurrent >= NextProgressUpdate)
                    {
                        OwnerWindow.ToolStripProgressBar.PerformStep();
                        NextProgressUpdate += ProgressInterval;
                        Debug.WriteLine("FCallGraphTreeViewParser.ParseSnapshot " + OwnerWindow.ToolStripProgressBar.Value + "/20");
                    }
                    CallStackCurrent++;

                    // Add this call graph to the tree view.
                    FCallStack CallStack = FStreamInfo.GlobalInstance.CallStackArray[AllocationInfo.CallStackIndex];
                    // Split the tree into full and truncated callstacks.
                    var RootNode = CallStack.bIsTruncated ? TruncatedNode : RegularNode;
                    // Apply filter based on text representation of address.
                    if (CallStack.RunFilters(FilterText, OwnerWindow.Options.ClassGroups, bFilterIn, OwnerWindow.SelectedMemoryPool))
                    {
                        // Add call stack to proper part of graph.
                        AddCallStackToGraph(RootNode, CallStack, AllocationInfo, ParentFunctionIndex, bInvertCallStacks);
                    }
                }
            }

            Debug.WriteLine("FCallGraphTreeViewParser.ParseSnapshot - Sorting call graph tree for " + OwnerWindow.CurrentFilename);

            // Sort the nodes before adding them to the tree (sorting when in the tree is slow!).
            SortNodes(TruncatedNode, bShouldSortBySize);
            SortNodes(RegularNode, bShouldSortBySize);

            Debug.WriteLine("FCallGraphTreeViewParser.ParseSnapshot - Populating call graph tree for " + OwnerWindow.CurrentFilename);

            // Clear out existing nodes and add two root nodes. One for regular call stacks and one for truncated ones.
            CallGraphTreeView.Nodes.Clear();
            CallGraphTreeView.Tag = new FCallGraphTreeViewTag();
            AddRootTreeNode(TruncatedNode, CallGraphTreeView);
            AddRootTreeNode(RegularNode, CallGraphTreeView);

            CallGraphTreeView.BeforeExpand -= HandlePreExpandTreeNode;
            CallGraphTreeView.BeforeExpand += HandlePreExpandTreeNode;

            CallGraphTreeView.EndUpdate();

            OwnerWindow.ToolStripProgressBar.Visible = false;
        }