public static void SelectHistogramBar(FHistogramBar Bar) { if (Bar != SelectedHistogramBar) { // Cancel any subselection if the main selection is changing. SubselectedHistogramBar = null; } SelectedHistogramBar = Bar; if (SelectedHistogramBar != null) { HistogramSelectionBars.Clear(); foreach (FCallStackAllocationInfo AllocationInfo in SelectedHistogramBar.CallStackList) { int Address = FStreamInfo.GlobalInstance.CallStackArray[AllocationInfo.CallStackIndex].AddressIndices[0]; string FunctionName = FStreamInfo.GlobalInstance.NameArray[FStreamInfo.GlobalInstance.CallStackAddressArray[Address].FunctionIndex]; FHistogramBar AllocBar = new FHistogramBar(FunctionName, SelectedHistogramBar.Colour); AllocBar.AddAllocation(AllocationInfo); HistogramSelectionBars.Add(AllocBar); } } UpdateHistogramDetails(); OwnerWindow.HistogramPanel.Invalidate(); }
public static void ClearView() { if (HistogramBars != null) { HistogramBars[0].Clear(); HistogramBars[1].Clear(); } HistogramSelectionBars.Clear(); SelectedMemoryBankIndex = 0; SelectedHistogramBarIndex[0] = 0; SelectedHistogramBarIndex[1] = 0; SelectedHistogramBar = null; SubselectedHistogramBar = null; OwnerWindow.HistogramViewCallStackListView.BeginUpdate(); OwnerWindow.HistogramViewCallStackListView.Items.Clear(); OwnerWindow.HistogramViewCallStackListView.SelectedItems.Clear(); OwnerWindow.HistogramViewCallStackListView.EndUpdate(); OwnerWindow.HistogramViewNameLabel.Text = ""; OwnerWindow.HistogramViewSizeLabel.Text = ""; OwnerWindow.HistogramViewAllocationsLabel.Text = ""; OwnerWindow.MemoryBitmapAllocatedMemoryLabel.Text = ""; }
/// <summary> Pen used to draw the selected histogram bar. Size of the checker is based on the selection height. </summary> private static Pen SelectedBarPen(FHistogramBar HistogramBar) { int SelectionHeight = ( int )HistogramBar.Rect.Height; if (SelectionHeight < 8) { return(CheckerPen1x1); } else if (SelectionHeight < 16) { return(CheckerPen2x2); } return(CheckerPen4x4); }
/// <summary> Pen used to draw the selected histogram bar. Size of the checker is based on the selection height. </summary> private static Pen SelectedBarPen( FHistogramBar HistogramBar ) { int SelectionHeight = ( int )HistogramBar.Rect.Height; if( SelectionHeight < 8 ) { return CheckerPen1x1; } else if( SelectionHeight < 16 ) { return CheckerPen2x2; } return CheckerPen4x4; }
static public void UnsafeMouseClick(object sender, MouseEventArgs e) { // Work out which bar, if any, the user clicked on. for (int MemoryBankIndex = 0; MemoryBankIndex < HistogramBars.Length; MemoryBankIndex++) { for (int BarIndex = 0; BarIndex < HistogramBars[MemoryBankIndex].Count; BarIndex++) { FHistogramBar Bar = FHistogramParser.HistogramBars[MemoryBankIndex][BarIndex]; if (Bar.Rect.Contains(e.X, e.Y)) { SelectedMemoryBankIndex = MemoryBankIndex; SelectedHistogramBarIndex[SelectedMemoryBankIndex] = BarIndex; SelectHistogramBar(Bar); if (e.Button == MouseButtons.Right) { OwnerWindow.ViewHistoryContextMenu.Tag = Bar; OwnerWindow.ViewHistoryContextMenu.Show(( Control )sender, e.Location); } return; } } } // Check selection bars (the graph that appears when you select a bar in another graph). if (SelectedHistogramBar != null) { for (int DetailedBarIndex = 0; DetailedBarIndex < HistogramSelectionBars.Count; DetailedBarIndex++) { FHistogramBar HistogramBar = HistogramSelectionBars[DetailedBarIndex]; if (HistogramBar.Rect.Contains(e.X, e.Y)) { SubselectHistogramBar(HistogramBar); if (e.Button == MouseButtons.Right) { OwnerWindow.ViewHistoryContextMenu.Tag = HistogramBar; OwnerWindow.ViewHistoryContextMenu.Show(( Control )sender, e.Location); } return; } } } SubselectHistogramBar(null); }
private static void UpdateHistogramDetails() { OwnerWindow.HistogramViewCallStackListView.BeginUpdate(); OwnerWindow.HistogramViewCallStackListView.Items.Clear(); FHistogramBar Bar = null; if (SubselectedHistogramBar != null) { Bar = SubselectedHistogramBar; } else if (SelectedHistogramBar != null) { Bar = SelectedHistogramBar; } if (Bar != null) { if (Bar != SubselectedHistogramBar) { OwnerWindow.HistogramViewNameLabel.Text = Bar.Description; } OwnerWindow.HistogramViewSizeLabel.Text = MainWindow.FormatSizeString2(Bar.MemorySize); OwnerWindow.HistogramViewAllocationsLabel.Text = Bar.AllocationCount.ToString("N0"); if (Bar.CallStackList.Count == 1) { foreach (int AddressIndex in FStreamInfo.GlobalInstance.CallStackArray[Bar.CallStackList[0].CallStackIndex].AddressIndices) { string FunctionName = FStreamInfo.GlobalInstance.NameArray[FStreamInfo.GlobalInstance.CallStackAddressArray[AddressIndex].FunctionIndex]; OwnerWindow.HistogramViewCallStackListView.Items.Add(FunctionName); } } } OwnerWindow.HistogramViewCallStackListView.EndUpdate(); }
/// <summary> Selects first valid histogram bar, searches through all memory banks. </summary> private static void SelectFirstValidHistogramBar() { SelectedMemoryBankIndex = 0; SelectedHistogramBarIndex[0] = 0; SelectedHistogramBarIndex[1] = 0; SubselectedHistogramBar = null; for (int MemoryBankIndex = 0; MemoryBankIndex < HistogramBars.Length; MemoryBankIndex++) { for (int BarIndex = 0; BarIndex < HistogramBars[MemoryBankIndex].Count; BarIndex++) { FHistogramBar Bar = FHistogramParser.HistogramBars[MemoryBankIndex][BarIndex]; if (Bar.AllocationCount > 0) { SelectedMemoryBankIndex = MemoryBankIndex; SelectedHistogramBarIndex[SelectedMemoryBankIndex] = BarIndex; SelectHistogramBar(Bar); return; } } } SelectedHistogramBar = null; }
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 SubselectHistogramBar(FHistogramBar HistogramBar) { SubselectedHistogramBar = HistogramBar; UpdateHistogramDetails(); OwnerWindow.HistogramPanel.Invalidate(); }
public static void PaintPanel(PaintEventArgs e) { int[] MemorySizes = new int[] { FStreamInfo.GetMemoryBankSize(0), FStreamInfo.GetMemoryBankSize(1) }; string[] MemoryCaptions = new string[] { "MB (Local)", "MB (Video)" }; const int MinorTick = 2; const int MajorTick = 10; const int TickRight = 70; const int GraphYBorder = 30; const int BarLeft = TickRight + 10; int NumColumns = 3; int TotalBordersSize = NumColumns * BarLeft; int GraphWidth = Math.Min((OwnerWindow.HistogramPanel.Width - TotalBordersSize) / 3, 150); float BarWidth = GraphWidth * 0.6f; float GraphXGap = GraphWidth * 0.4f; int MaxMemorySize = 0; for (int BankIndex = 0; BankIndex < NUM_MEMORY_BANKS; BankIndex++) { MaxMemorySize = Math.Max(MemorySizes[BankIndex], MaxMemorySize); } float TotalGraphHeight = OwnerWindow.HistogramPanel.Height - GraphYBorder * 2; if (HistogramBars != null) { for (int MemoryBankIndex = 0; MemoryBankIndex < MemorySizes.Length; MemoryBankIndex++) { float GraphTop = GraphYBorder; float GraphLeft = MemoryBankIndex * (BarLeft + BarWidth + GraphXGap); float YScale = TotalGraphHeight / MemorySizes[MemoryBankIndex]; // Draw vertical axes. OwnerWindow.DrawYAxis(e.Graphics, Pens.Black, Color.Black, MajorTick, MinorTick, GraphLeft + TickRight, GraphTop, TotalGraphHeight, MemoryCaptions[MemoryBankIndex], MemorySizes[MemoryBankIndex]); float BarY = GraphTop + YScale * MemorySizes[MemoryBankIndex]; for (int BarIndex = HistogramBars[MemoryBankIndex].Count - 1; BarIndex >= 0; BarIndex--) { FHistogramBar Bar = HistogramBars[MemoryBankIndex][BarIndex]; if (Bar.AllocationCount == 0) { continue; } float BarHeight = ( float )Bar.MemorySize / (1024 * 1024) * YScale; Bar.Rect.X = GraphLeft + BarLeft; Bar.Rect.Y = BarY - BarHeight; Bar.Rect.Width = BarWidth; Bar.Rect.Height = BarHeight; e.Graphics.FillRectangle(new SolidBrush(Bar.Colour), Bar.Rect.X, Bar.Rect.Y, Bar.Rect.Width, Bar.Rect.Height); BarY -= BarHeight; } } if (SelectedHistogramBar != null) { e.Graphics.FillRectangle ( SelectedBarPen(SelectedHistogramBar).Brush, SelectedHistogramBar.Rect.X, SelectedHistogramBar.Rect.Y, SelectedHistogramBar.Rect.Width, Math.Max(SelectedHistogramBar.Rect.Height, 1.0f) ); float MarkerHeight = Math.Max(SelectedHistogramBar.Rect.Height, 1.0f); float MarkerPosX = SelectedHistogramBar.Rect.Left + SelectedHistogramBar.Rect.Width + 1.0f; float MarkerPosY = ( float )Math.Ceiling(( double )SelectedHistogramBar.Rect.Top) - 1; e.Graphics.DrawLine(Pens.Black, MarkerPosX + 0, MarkerPosY, MarkerPosX + 5, MarkerPosY); e.Graphics.DrawLine(Pens.Black, MarkerPosX + 5, MarkerPosY, MarkerPosX + 5, MarkerPosY + MarkerHeight); e.Graphics.DrawLine(Pens.Black, MarkerPosX + 0, MarkerPosY + MarkerHeight + 1, MarkerPosX + 5, MarkerPosY + MarkerHeight + 1); } TextRenderer.DrawText( e.Graphics, "Use key up or key down to change selected allocation", OwnerWindow.AxisFont, new Point((int)(BarLeft * 0.5f), (int)(OwnerWindow.HistogramPanel.Height - (GraphYBorder + OwnerWindow.AxisFont.Height) * 0.5f)), Color.Black ); } /* * // Draw "Total Memory Used" line. * if( OwnerWindow.CurrentSnapshot != null && OwnerWindow.CurrentSnapshot.MetricArray.Count > 0 ) * { * float YScale = TotalGraphHeight / MemorySizes[ 0 ]; * float GraphBottom = GraphYBorder + YScale * MemorySizes[ 0 ]; * float TotalUsedLineY = GraphBottom - YScale * ( OwnerWindow.CurrentSnapshot.MemoryAllocationStats.TotalAllocated / 1024f / 1024f ); * float OverheadLineY = TotalUsedLineY + YScale * ( OwnerWindow.CurrentSnapshot.MetricArray[ ( int )ESnapshotMetricV3.MemoryProfilingOverhead ] / 1024f / 1024f ); * * e.Graphics.DrawLine( BlackDashedPen, TickRight, TotalUsedLineY, BarLeft + BarWidth, TotalUsedLineY ); * e.Graphics.DrawLine( RedDashedPen, TickRight, OverheadLineY, BarLeft + BarWidth, OverheadLineY ); * } */ if (SelectedHistogramBar != null && SelectedHistogramBar.MemorySize > 0) { float GraphLeft = MemorySizes.Length * (BarLeft + BarWidth + GraphXGap); float MemorySizeMB = ( float )(( double )SelectedHistogramBar.MemorySize / (1024 * 1024)); float SelectedYScale = TotalGraphHeight / MemorySizeMB; string AxisLabel = "MB"; int AxisMemorySize = ( int )MemorySizeMB; if (AxisMemorySize < 32) { // Drop down into kilobytes. AxisMemorySize = ( int )(SelectedHistogramBar.MemorySize / 1024); AxisLabel = "KB"; } if (AxisMemorySize < 32) { // Drop down into bytes. AxisMemorySize = ( int )Math.Max(SelectedHistogramBar.MemorySize, 32); AxisLabel = "bytes"; } // Select a major tick that's divisible by 4 so that the minor tick divides into it without remainder. int SelectedMajorTick = (AxisMemorySize / 8) / 4 * 4; int SelectedMinorTick = SelectedMajorTick / 4; OwnerWindow.DrawYAxis(e.Graphics, Pens.Black, Color.Black, SelectedMajorTick, SelectedMinorTick, GraphLeft + TickRight, GraphYBorder, TotalGraphHeight, AxisLabel, AxisMemorySize); { // Used to batch up drawing as individual calls are slow var FillRects = new Dictionary <Color, List <RectangleF> >(); var DrawRects = new List <RectangleF>(); float BarY = GraphYBorder + SelectedYScale * MemorySizeMB; for (int SelBarIndex = HistogramSelectionBars.Count - 1; SelBarIndex >= 0; SelBarIndex--) { FHistogramBar Bar = HistogramSelectionBars[SelBarIndex]; float BarHeight = (float)((double)Bar.MemorySize / (1024 * 1024) * SelectedYScale); Bar.Rect.X = GraphLeft + BarLeft; Bar.Rect.Y = BarY - BarHeight; Bar.Rect.Width = BarWidth; Bar.Rect.Height = BarHeight; List <RectangleF> FillRectsList; if (FillRects.TryGetValue(Bar.Colour, out FillRectsList)) { FillRectsList.Add(new RectangleF(Bar.Rect.X, Bar.Rect.Y, Bar.Rect.Width, Bar.Rect.Height)); } else { FillRectsList = new List <RectangleF>() { new RectangleF(Bar.Rect.X, Bar.Rect.Y, Bar.Rect.Width, Bar.Rect.Height) }; FillRects.Add(Bar.Colour, FillRectsList); } DrawRects.Add(new RectangleF(Bar.Rect.X, Bar.Rect.Y, Bar.Rect.Width - 1, Bar.Rect.Height)); BarY -= BarHeight; } // Draw batched foreach (var FillRectPair in FillRects) { e.Graphics.FillRectangles(new SolidBrush(FillRectPair.Key), FillRectPair.Value.ToArray()); } e.Graphics.DrawRectangles(Pens.Black, DrawRects.ToArray()); } if (SubselectedHistogramBar != null) { e.Graphics.FillRectangle ( SelectedBarPen(SubselectedHistogramBar).Brush, SubselectedHistogramBar.Rect.X, SubselectedHistogramBar.Rect.Y, SubselectedHistogramBar.Rect.Width, Math.Max(SubselectedHistogramBar.Rect.Height, 1.0f) ); float MarkerHeight = Math.Max(SubselectedHistogramBar.Rect.Height, 1.0f); float MarkerPosX = SubselectedHistogramBar.Rect.Left + SubselectedHistogramBar.Rect.Width + 1.0f; float MarkerPosY = ( float )Math.Ceiling(( double )SubselectedHistogramBar.Rect.Top) - 1; e.Graphics.DrawLine(Pens.Black, MarkerPosX + 0, MarkerPosY, MarkerPosX + 5, MarkerPosY); e.Graphics.DrawLine(Pens.Black, MarkerPosX + 5, MarkerPosY, MarkerPosX + 5, MarkerPosY + MarkerHeight); e.Graphics.DrawLine(Pens.Black, MarkerPosX + 0, MarkerPosY + MarkerHeight + 1, MarkerPosX + 5, MarkerPosY + MarkerHeight + 1);; } } }
public static void SubselectHistogramBar( FHistogramBar HistogramBar ) { SubselectedHistogramBar = HistogramBar; UpdateHistogramDetails(); OwnerWindow.HistogramPanel.Invalidate(); }
public static void SelectHistogramBar( FHistogramBar Bar ) { if( Bar != SelectedHistogramBar ) { // Cancel any subselection if the main selection is changing. SubselectedHistogramBar = null; } SelectedHistogramBar = Bar; if( SelectedHistogramBar != null ) { HistogramSelectionBars.Clear(); foreach( FCallStackAllocationInfo AllocationInfo in SelectedHistogramBar.CallStackList ) { int Address = FStreamInfo.GlobalInstance.CallStackArray[ AllocationInfo.CallStackIndex ].AddressIndices[ 0 ]; string FunctionName = FStreamInfo.GlobalInstance.NameArray[ FStreamInfo.GlobalInstance.CallStackAddressArray[ Address ].FunctionIndex ]; FHistogramBar AllocBar = new FHistogramBar( FunctionName, SelectedHistogramBar.Colour ); AllocBar.AddAllocation( AllocationInfo ); HistogramSelectionBars.Add( AllocBar ); } } UpdateHistogramDetails(); OwnerWindow.HistogramPanel.Invalidate(); }
public static void ClearView() { if( HistogramBars != null ) { HistogramBars[ 0 ].Clear(); HistogramBars[ 1 ].Clear(); } HistogramSelectionBars.Clear(); SelectedMemoryBankIndex = 0; SelectedHistogramBarIndex[ 0 ] = 0; SelectedHistogramBarIndex[ 1 ] = 0; SelectedHistogramBar = null; SubselectedHistogramBar = null; OwnerWindow.HistogramViewCallStackListView.BeginUpdate(); OwnerWindow.HistogramViewCallStackListView.Items.Clear(); OwnerWindow.HistogramViewCallStackListView.SelectedItems.Clear(); OwnerWindow.HistogramViewCallStackListView.EndUpdate(); OwnerWindow.HistogramViewNameLabel.Text = ""; OwnerWindow.HistogramViewSizeLabel.Text = ""; OwnerWindow.HistogramViewAllocationsLabel.Text = ""; OwnerWindow.MemoryBitmapAllocatedMemoryLabel.Text = ""; }
/// <summary> Selects first valid histogram bar, searches through all memory banks. </summary> private static void SelectFirstValidHistogramBar() { SelectedMemoryBankIndex = 0; SelectedHistogramBarIndex[ 0 ] = 0; SelectedHistogramBarIndex[ 1 ] = 0; SubselectedHistogramBar = null; for( int MemoryBankIndex = 0; MemoryBankIndex < HistogramBars.Length; MemoryBankIndex++ ) { for( int BarIndex = 0; BarIndex < HistogramBars[ MemoryBankIndex ].Count; BarIndex++ ) { FHistogramBar Bar = FHistogramParser.HistogramBars[ MemoryBankIndex ][ BarIndex ]; if( Bar.AllocationCount > 0 ) { SelectedMemoryBankIndex = MemoryBankIndex; SelectedHistogramBarIndex[ SelectedMemoryBankIndex ] = BarIndex; SelectHistogramBar( Bar ); return; } } } SelectedHistogramBar = null; }
/*----------------------------------------------------------------------------- Callstack history view helper functions -----------------------------------------------------------------------------*/ /// <summary> Set callstacks for the callstack history view based on selected histogram bar and starts processing. </summary> public void SetHistoryCallStacks( FHistogramBar Bar ) { // Collect callstack indices in a sorted list to make it easier // to filter out duplicate callstacks. List<int> CallstackIndices = new List<int>(); foreach( FCallStackAllocationInfo AllocInfo in Bar.CallStackList ) { bool bDone = false; for( int Index = 0; Index < CallstackIndices.Count; Index++ ) { if( CallstackIndices[ Index ] == AllocInfo.CallStackIndex ) { // callstack is already in the list bDone = true; break; } else if( CallstackIndices[ Index ] > AllocInfo.CallStackIndex ) { CallstackIndices.Insert( Index, AllocInfo.CallStackIndex ); bDone = true; break; } } if( !bDone ) { CallstackIndices.Add( AllocInfo.CallStackIndex ); } } List<FCallStack> Callstacks = new List<FCallStack>( CallstackIndices.Count ); foreach( int Index in CallstackIndices ) { Callstacks.Add( FStreamInfo.GlobalInstance.CallStackArray[ Index ] ); } SetHistoryCallStacks( Callstacks ); }
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; foreach( FCallStackAllocationInfo AllocationInfo in CallStackList ) { // 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, OwnerWindow.IsFilteringIn(), 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.Size; Count += AllocationInfo.Count; } } // 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(); }