/// <summary> Constructor. </summary>
 public FCallStackTag( FCallStack InCallStack, int InStartFrame, ulong InStreamIndex, ulong InPointer, ulong InSize )
 {
     CallStack = InCallStack;
     StreamIndex = InStreamIndex;
     Pointer = InPointer;
     Size = InSize;
 }
示例#2
0
 /// <summary> Constructor. </summary>
 public FAllocationEvent(FStreamToken StreamToken, FCallStack InPreviousCallStack, FAllocationLifecycle InPreviousLifecycle)
 {
     StreamIndex = StreamToken.StreamIndex;
     Pointer = StreamToken.Type == EProfilingPayloadType.TYPE_Realloc ? StreamToken.NewPointer : StreamToken.Pointer;
     Size = StreamToken.Size;
     PreviousCallStack = InPreviousCallStack;
     PreviousLifecycle = InPreviousLifecycle;
 }
		private static void InsertItemIntoMemoryBitmapListView( FCallStack CallStack, ulong StreamIndex, int StartFrame, int EndFrame, ulong AllocatedPointer, int AllocatedSize )
		{
			ListViewItem LVItem = new ListViewItem();
			LVItem.Text = StartFrame.ToString();
			LVItem.SubItems.Add( EndFrame == 0 ? "" : EndFrame.ToString() );
			LVItem.SubItems.Add( MainWindow.FormatSizeString( AllocatedSize ) );
			LVItem.Tag = new FCallStackTag( CallStack, StartFrame, StreamIndex, AllocatedPointer, ( ulong )AllocatedSize );

			bool bInserted = false;
			for( int ItemIndex = OwnerWindow.MemoryBitmapAllocationHistoryListView.Items.Count - 1; ItemIndex >= 0; ItemIndex-- )
			{
				if( ( ( FCallStackTag )OwnerWindow.MemoryBitmapAllocationHistoryListView.Items[ ItemIndex ].Tag ).StreamIndex <= StreamIndex )
				{
					OwnerWindow.MemoryBitmapAllocationHistoryListView.Items.Insert( ItemIndex + 1, LVItem );
					bInserted = true;
					break;
				}
			}

			if( !bInserted )
			{
				OwnerWindow.MemoryBitmapAllocationHistoryListView.Items.Insert( 0, LVItem );
			}
		}
		private static void ProcessLifecycleForPixel( ulong PointerFromPixel, FCallStack CallStack, FAllocationLifecycle AllocLifecycle, bool bUpdateEndFrame )
		{
			int StartFrame = 1;
			int EndFrame = 1;
			bool bAllocated = false;
			ulong AllocatedPointer = 0;
			int AllocatedSize = 0;
			ulong AllocatedStreamIndex = FStreamInfo.INVALID_STREAM_INDEX;

			if( AllocLifecycle.AllocEvent.Pointer <= PointerFromPixel
				&& AllocLifecycle.AllocEvent.Pointer + ( uint )AllocLifecycle.AllocEvent.Size > PointerFromPixel )
			{
				bAllocated = true;
				AllocatedPointer = AllocLifecycle.AllocEvent.Pointer;
				AllocatedSize = AllocLifecycle.AllocEvent.Size;
				AllocatedStreamIndex = AllocLifecycle.AllocEvent.StreamIndex;

				StartFrame = FStreamInfo.GlobalInstance.GetFrameNumberFromStreamIndex( EndFrame, AllocLifecycle.AllocEvent.StreamIndex );
			}

			if( AllocLifecycle.ReallocsEvents != null )
			{
				for( int EventIndex = 0; EventIndex < AllocLifecycle.ReallocsEvents.Count; EventIndex++ )
				{
					if( bAllocated )
					{
						if( AllocLifecycle.ReallocsEvents[ EventIndex ].NewPointer > PointerFromPixel
							|| AllocLifecycle.ReallocsEvents[ EventIndex ].NewPointer + ( uint )AllocLifecycle.ReallocsEvents[ EventIndex ].NewSize < PointerFromPixel )
						{
							bAllocated = false;
							EndFrame = FStreamInfo.GlobalInstance.GetFrameNumberFromStreamIndex( StartFrame, AllocLifecycle.ReallocsEvents[ EventIndex ].StreamIndex );

							InsertItemIntoMemoryBitmapListView( CallStack, AllocatedStreamIndex, StartFrame, EndFrame, AllocatedPointer, AllocatedSize );
						}
					}
					else if( AllocLifecycle.ReallocsEvents[ EventIndex ].NewPointer <= PointerFromPixel
							&& AllocLifecycle.ReallocsEvents[ EventIndex ].NewPointer + ( uint )AllocLifecycle.ReallocsEvents[ EventIndex ].NewSize > PointerFromPixel )
					{
						bAllocated = true;
						AllocatedPointer = AllocLifecycle.ReallocsEvents[ EventIndex ].NewPointer;
						AllocatedSize = AllocLifecycle.ReallocsEvents[ EventIndex ].NewSize;
						AllocatedStreamIndex = AllocLifecycle.ReallocsEvents[ EventIndex ].StreamIndex;

						StartFrame = FStreamInfo.GlobalInstance.GetFrameNumberFromStreamIndex( EndFrame, AllocLifecycle.ReallocsEvents[ EventIndex ].StreamIndex );
					}
				}
			}

			if( bAllocated )
			{
				if( bUpdateEndFrame )
				{
					EndFrame = AllocLifecycle.FreeStreamIndex == FStreamInfo.INVALID_STREAM_INDEX
							? -1
							: FStreamInfo.GlobalInstance.GetFrameNumberFromStreamIndex( StartFrame, AllocLifecycle.FreeStreamIndex );
				}
				else
				{
					EndFrame = 0;
				}

				InsertItemIntoMemoryBitmapListView( CallStack, AllocatedStreamIndex, StartFrame, EndFrame, AllocatedPointer, AllocatedSize );
			}
		}
		public FShortLivedCallStackTag( FCallStack InCallStack, uint[] InColumnValues )
		{
			CallStack = InCallStack;
			ColumnValues = InColumnValues;
		}
		private static int GetVirtualCallStackIndex( FStreamToken StreamToken, StreamObserver Observer )
		{
			if( StreamToken.ScriptCallstackIndex == -1 && StreamToken.ScriptObjectTypeIndex == -1 )
			{
				return StreamToken.CallStackIndex;
			}

			FCallStack OriginalCallStack = FStreamInfo.GlobalInstance.CallStackArray[ StreamToken.CallStackIndex ];
			FScriptCallStack ScriptCallStack = StreamToken.ScriptCallstackIndex == -1 ? null : FStreamInfo.GlobalInstance.ScriptCallstackArray[ StreamToken.ScriptCallstackIndex ];

			// Get the script-object type for this index (if it's not cached, create a ScriptObjectType instance and cache it).
			FScriptObjectType ScriptObjectType = null;
			if( StreamToken.ScriptObjectTypeIndex != -1 )
			{
				if( !FStreamInfo.GlobalInstance.ScriptObjectTypeMapping.TryGetValue( StreamToken.ScriptObjectTypeIndex, out ScriptObjectType ) )
				{
					ScriptObjectType = new FScriptObjectType( FStreamInfo.GlobalInstance.ScriptNameArray[ StreamToken.ScriptObjectTypeIndex ] );
					FStreamInfo.GlobalInstance.ScriptObjectTypeMapping.Add( StreamToken.ScriptObjectTypeIndex, ScriptObjectType );
				}
			}

			for( int ChildIndex = 0; ChildIndex < OriginalCallStack.Children.Count; ChildIndex++ )
			{
				if( ( OriginalCallStack.Children[ ChildIndex ].ScriptCallStack == ScriptCallStack )
					&& ( OriginalCallStack.Children[ ChildIndex ].ScriptObjectType == ScriptObjectType ) )
				{
					return OriginalCallStack.ChildIndices[ ChildIndex ];
				}
			}

			FCallStack NewCallStack = new FCallStack( OriginalCallStack, ScriptCallStack, ScriptObjectType, FStreamInfo.GlobalInstance.CallStackArray.Count );
			FStreamInfo.GlobalInstance.CallStackArray.Add( NewCallStack );

			return FStreamInfo.GlobalInstance.CallStackArray.Count - 1;
		}
		public bool ContainsCallStack(FCallStack OtherCallStack)
		{
			return CallStacksSet.Contains(OtherCallStack);
		}
示例#8
0
		/// <summary> Processes realloc operation for this allocation lifecycle. </summary>
		public void Realloc(FStreamToken StreamToken, FCallStack InitialCallStack, out int SizeChange)
		{
			// reallocs that are really frees should be handled by free()
			Debug.Assert(StreamToken.Size > 0);

			int InitialSize = CurrentSize;

			LatestPointer = StreamToken.NewPointer;
			FCallStack ReallocCallStack = FStreamInfo.GlobalInstance.CallStackArray[StreamToken.CallStackIndex];

			if (ReallocsEvents == null)
			{
				ReallocsEvents = new List<FReallocationEvent>();
			}
			ReallocsEvents.Add(new FReallocationEvent(StreamToken, ReallocCallStack));
			ReallocsEvents.TrimExcess();

			if (ReallocCallStack != InitialCallStack)
			{
				// pointer has been realloced by a different callstack
				// it hasn't been freed, but it won't be tracked by this lifecycle object anymore,
				// so mark this object complete
				SizeChange = -InitialSize;
				bIsComplete = true;
			}
			else
			{
				SizeChange = StreamToken.Size - InitialSize;
			}

			if (AllocEvent.PreviousCallStack != null)
			{
				AllocEvent.PreviousCallStack.PropagateSizeGraphPoint(AllocEvent.PreviousLifecycle, StreamToken.StreamIndex, SizeChange);
			}
		}
示例#9
0
		/// <summary> Processes realloc operation for this callstack and updates lifecycles if needed. </summary>
		public FAllocationLifecycle ProcessRealloc(FStreamToken StreamToken, ref FAllocationLifecycle NewLifecycle, FCallStack PreviousCallStack, FAllocationLifecycle PreviousLifecycle)
		{
			FAllocationLifecycle Result = null;
			int SizeChange = 0;
			bool bFreshRealloc = true;

			FAllocationLifecycle Lifecycle;
			if (IncompleteLifecycles.TryGetValue(StreamToken.OldPointer, out Lifecycle))
			{
				IncompleteLifecycles.Remove(StreamToken.OldPointer);
				Lifecycle.Realloc(StreamToken, this, out SizeChange);
				if (Lifecycle.bIsComplete)
				{
					if (FStreamInfo.GlobalInstance.CreationOptions.KeepLifecyclesCheckBox.Checked)
					{
						CompleteLifecycles.Add(Lifecycle);
					}
				}
				else
				{
					IncompleteLifecycles.Add(Lifecycle.LatestPointer, Lifecycle);
				}

				bFreshRealloc = false;
				Result = Lifecycle;
			}
			else
			{
				Debug.Assert(NewLifecycle != null);
				NewLifecycle.Malloc(StreamToken, PreviousCallStack, PreviousLifecycle);
				Result = NewLifecycle;
				NewLifecycle = null;

				IncompleteLifecycles.Add(Result.LatestPointer, Result);

				bFreshRealloc = true;
				SizeChange = StreamToken.Size;
			}

			LatestSize += SizeChange;
			if (LatestSize > MaxSize)
			{
				MaxSize = LatestSize;
			}

			// it's possible that this point was already added to the graph via realloc chain propagation
			if (SizeGraphPoints != null && (SizeGraphPoints.Count == 0 || SizeGraphPoints[SizeGraphPoints.Count - 1].StreamIndex != StreamToken.StreamIndex))
			{
				SizeGraphPoints.Add(new FSizeGraphPoint(StreamToken.StreamIndex, SizeChange, bFreshRealloc));
			}

			return Result;
		}
        private static void AddCallStackToGraph( TreeNode RootNode, FCallStack CallStack, FCallStackAllocationInfo AllocationInfo, int ParentFunctionIndex, bool bInvertCallStacks )
        {
            // Used to determine whether it is okay to add address to the graph. An index of -1 means we don't care about parenting.
            bool bAllowNodeUpdate = ParentFunctionIndex == -1;
            // Iterate over each address and add it to the tree view.
            TreeNode CurrentNode = RootNode;
            for( int AdressIndex = 0; AdressIndex < CallStack.AddressIndices.Count; AdressIndex++ )
            {
                int AddressIndex;
                if( bInvertCallStacks )
                {
                    AddressIndex = CallStack.AddressIndices[ CallStack.AddressIndices.Count - 1 - AdressIndex ];
                }
                else
                {
                    AddressIndex = CallStack.AddressIndices[ AdressIndex ];
                }

                // Filter based on function if wanted. This means we only include callstacks that contain the function
                // and we also reparent the callstack to start at the first occurence of the function.
                if( ParentFunctionIndex != -1 && !bAllowNodeUpdate )
                {
                    bAllowNodeUpdate = FStreamInfo.GlobalInstance.CallStackAddressArray[ AddressIndex ].FunctionIndex == ParentFunctionIndex;
                }

                if( bAllowNodeUpdate )
                {
                    // Update the node for this address. The return value of the function will be the new parent node.
                    CurrentNode = UpdateNodeAndPayload( CurrentNode, AddressIndex, AllocationInfo );
                }
            }
        }
示例#11
0
        public bool Matches(FCallStack CallStack)
        {
            if (StackFramePatterns.Length == 0)
            {
                return false;
            }

            int PatternIndex = 0;

			if( bUseRegexes )
			{
				for( int i = 0; i < CallStack.AddressIndices.Count; i++ )
				{
					string CallStackMethod = FStreamInfo.GlobalInstance.NameArray[ FStreamInfo.GlobalInstance.CallStackAddressArray[ CallStack.AddressIndices[ i ] ].FunctionIndex ];
					if( Regexes[ PatternIndex ].Match( CallStackMethod ).Success )
					{
						PatternIndex++;
						if( PatternIndex >= StackFramePatterns.Length )
						{
							return true;
						}
					}
				}
			}
			else
			{
				for( int i = 0; i < CallStack.AddressIndices.Count; i++ )
				{
					string CallStackMethod = FStreamInfo.GlobalInstance.NameArray[ FStreamInfo.GlobalInstance.CallStackAddressArray[ CallStack.AddressIndices[ i ] ].FunctionIndex ];
					if( CallStackMethod == StackFramePatterns[ PatternIndex ] )
					{
						PatternIndex++;
						if( PatternIndex >= StackFramePatterns.Length )
						{
							return true;
						}
					}
				}
			}

            return false;
        }
示例#12
0
		public virtual void ResolveCallstackSymbolInfoAsync(ESymbolResolutionMode SymbolResolutionMode, FCallStack CallStack, ResolveCallstackSymbolInfoCallback Callback, bool bCancelCurrentWork)
		{
			if (bCancelCurrentWork)
			{
				foreach (var Worker in ResolveCallstackSymbolInfoAsyncTasks)
				{
					if (Worker.IsBusy && !Worker.CancellationPending)
					{
						Worker.CancelAsync();
					}
				}
			}

			for (int WorkerIndex = ResolveCallstackSymbolInfoAsyncTasks.Count - 1; WorkerIndex >= 0; --WorkerIndex)
			{
				var Worker = ResolveCallstackSymbolInfoAsyncTasks[WorkerIndex];
				if (!Worker.IsBusy)
				{
					ResolveCallstackSymbolInfoAsyncTasks.RemoveAt(WorkerIndex);
				}
			}

			var AsyncWorker = new BackgroundWorker();

			AsyncWorker.DoWork += new DoWorkEventHandler(delegate(object Obj, DoWorkEventArgs Args)
			{
				var Worker = Obj as BackgroundWorker;

				foreach (int AddressIndex in CallStack.AddressIndices)
				{
					if (Worker.CancellationPending)
					{
						break;
					}

					FCallStackAddress Address = FStreamInfo.GlobalInstance.CallStackAddressArray[AddressIndex];
					ResolveAddressSymbolInfo(SymbolResolutionMode, Address);
				}

				if (!Worker.CancellationPending)
				{
					Callback(CallStack);
				}
			});

			AsyncWorker.RunWorkerAsync();
			ResolveCallstackSymbolInfoAsyncTasks.Add(AsyncWorker);
		}
示例#13
0
		public virtual bool ResolveCallstackSymbolInfo(ESymbolResolutionMode SymbolResolutionMode, FCallStack CallStack)
		{
			bool bSuccess = true;

			foreach (int AddressIndex in CallStack.AddressIndices)
			{
				FCallStackAddress Address = FStreamInfo.GlobalInstance.CallStackAddressArray[AddressIndex];
				bSuccess &= ResolveAddressSymbolInfo(SymbolResolutionMode, Address);
			}

			return bSuccess;
		}
		/// <summary> Constructor, initializing all members with passed in values. </summary>
		public FCallGraphNode(FCallGraphNode InParent, int InAddressIndex, long InAllocationSize, int InAllocationCount, string InFunctionName, FCallStack CallStack)
		{
			Parent = InParent;
			if (Parent != null)
			{
				Parent.Children.Add(this);
			}

			AddressIndex = InAddressIndex;
			AllocationSize = InAllocationSize;
			AllocationCount = InAllocationCount;
			FunctionName = InFunctionName;
			CallStacks.Add(CallStack);
		}
示例#15
0
		/// <summary> Based on original callstack initializes a new callstack with decoded script callstack and script object type. </summary>
		public FCallStack(FCallStack InOriginal, FScriptCallStack InScriptCallStack, FScriptObjectType InScriptObjectType, int InCallStackIndex)
			: this()
		{
			Debug.Assert(InOriginal != null);
			Debug.Assert(ScriptCallStack == null || ScriptCallStack.Frames.Length > 0);

			Original = InOriginal;
			ScriptCallStack = InScriptCallStack;
			ScriptObjectType = InScriptObjectType;

			Original.Children.Add(this);
			Original.ChildIndices.Add(InCallStackIndex);

			CRC = Original.CRC;
			AddressIndices = new List<int>(Original.AddressIndices);
			FirstNonContainer = AddressIndices.Count - 1;
			bIsTruncated = Original.bIsTruncated;

			// If there is a script call stack, rename functions
			if (ScriptCallStack != null)
			{
				int ScriptFrameIndex = 0;
				for (int AddressIndex = AddressIndices.Count - 1; AddressIndex >= 0; AddressIndex--)
				{
					int FunctionNameIndex = FStreamInfo.GlobalInstance.CallStackAddressArray[AddressIndices[AddressIndex]].FunctionIndex;
					if (FunctionNameIndex == FStreamInfo.GlobalInstance.ProcessInternalNameIndex)
					{
						AddressIndices[AddressIndex] = ScriptCallStack.Frames[ScriptFrameIndex].CallStackAddressIndex;
						ScriptFrameIndex++;
						if (ScriptFrameIndex >= ScriptCallStack.Frames.Length)
						{
							break;
						}
					}
				}
			}

			// If the call stack has a script type allocation, replace the StaticAllocateObject call with the appropriate type-tagged one
			if (ScriptObjectType != null)
			{
				for (int AddressIndex = AddressIndices.Count - 1; AddressIndex >= 0; AddressIndex--)
				{
					int FunctionNameIndex = FStreamInfo.GlobalInstance.CallStackAddressArray[AddressIndices[AddressIndex]].FunctionIndex;
					if (FunctionNameIndex == FStreamInfo.GlobalInstance.StaticAllocateObjectNameIndex)
					{
						AddressIndices[AddressIndex] = ScriptObjectType.CallStackAddressIndex;
						break;
					}
				}
			}
		}
 /// <summary> Constructor, initializing all members with passed in values. </summary>
 public FNodePayload( int InAddressIndex, long InAllocationSize, int InAllocationCount, FCallStack CallStack )
 {
     AddressIndex = InAddressIndex;
     AllocationSize = InAllocationSize;
     AllocationCount = InAllocationCount;
     CallStacks.Add( CallStack );
 }
示例#17
0
		/// <summary> Compares two callstacks for sorting. </summary>
		/// <param name="A"> First callstack to compare </param>
		/// <param name="B"> Second callstack to compare </param>
		public static int Compare(FCallStack A, FCallStack B)
		{
			// Not all callstacks have the same depth. Figure out min for comparision.
			int MinSize = Math.Min(A.AddressIndices.Count, B.AddressIndices.Count);

			// Iterate over matching size and compare.
			for (int i = 0; i < MinSize; i++)
			{
				// Sort by address
				if (A.AddressIndices[i] > B.AddressIndices[i])
				{
					return 1;
				}
				else if (A.AddressIndices[i] < B.AddressIndices[i])
				{
					return -1;
				}
			}

			// If we got here it means that the subset of addresses matches. In theory this means
			// that the callstacks should have the same size as you can't have the same address
			// doing the same thing, but let's simply be thorough and handle this case if the
			// stackwalker isn't 100% accurate.

			// Matching length means matching callstacks.
			if (A.AddressIndices.Count == B.AddressIndices.Count)
			{
				return 0;
			}
			// Sort by additional length.
			else
			{
				return A.AddressIndices.Count > B.AddressIndices.Count ? 1 : -1;
			}
		}
 public virtual void AllocationEvent( FCallStack Callstack, EProfilingPayloadType EventType, long Size )
 {
 }
示例#19
0
		/// <summary> Processes malloc operation for this allocation lifecycle. </summary>
		public void Malloc(FStreamToken StreamToken, FCallStack PreviousCallStack, FAllocationLifecycle PreviousLifecycle)
		{
			AllocEvent = new FAllocationEvent(StreamToken, PreviousCallStack, PreviousLifecycle);
			LatestPointer = AllocEvent.Pointer;

			// if PreviousCallStack != null, initial allocation was made by another callstack
			if (PreviousCallStack != null)
			{
				PreviousCallStack.PropagateSizeGraphPoint(PreviousLifecycle, StreamToken.StreamIndex, StreamToken.Size);
			}
		}
 public virtual void NewCallstack( FCallStack Callstack )
 {
 }
示例#21
0
		/// <summary> Constructor. </summary>
		public FReallocationEvent(FStreamToken StreamToken, FCallStack InCallstack)
		{
			StreamIndex = StreamToken.StreamIndex;
			NewPointer = StreamToken.NewPointer;
			NewSize = StreamToken.Size;
		}
		public void AddCallStack(FCallStack NewCallStack)
		{
			CallStacks.Add(NewCallStack);
			CallStacksSet.Add(NewCallStack);
		}