/// <summary> Returns a difference between old and new memory allocation stats. </summary> public static FMemoryAllocationStatsV3 Diff(FMemoryAllocationStatsV3 Old, FMemoryAllocationStatsV3 New) { FMemoryAllocationStatsV3 Diff = new FMemoryAllocationStatsV3(); FieldInfo[] FieldInfos = typeof(FMemoryAllocationStatsV3).GetFields(); int PropertiesNum = FieldInfos.Length; for (int FieldIndex = 0; FieldIndex < PropertiesNum; FieldIndex++) { Int64 OldValue = (Int64)FieldInfos[FieldIndex].GetValue(Old); Int64 NewValue = (Int64)FieldInfos[FieldIndex].GetValue(New); FieldInfos[FieldIndex].SetValue(Diff, NewValue - OldValue); } return(Diff); }
/// <summary> Diffs two snapshots and creates a result one. </summary> public static FStreamSnapshot DiffSnapshots(FStreamSnapshot Old, FStreamSnapshot New) { // Create result snapshot object. FStreamSnapshot ResultSnapshot = new FStreamSnapshot("Diff " + Old.Description + " <-> " + New.Description); using (FScopedLogTimer LoadingTime = new FScopedLogTimer("FStreamSnapshot.DiffSnapshots")) { // Copy over allocation count so we can track where the graph starts ResultSnapshot.AllocationCount = Old.AllocationCount; Debug.Assert(Old.MetricArray.Count == New.MetricArray.Count); ResultSnapshot.MetricArray = new List <long>(Old.MetricArray.Count); for (int CallstackIndex = 0; CallstackIndex < Old.MetricArray.Count; CallstackIndex++) { ResultSnapshot.MetricArray.Add(New.MetricArray[CallstackIndex] - Old.MetricArray[CallstackIndex]); } ResultSnapshot.MemoryAllocationStats3 = FMemoryAllocationStatsV3.Diff(Old.MemoryAllocationStats3, New.MemoryAllocationStats3); ResultSnapshot.MemoryAllocationStats4 = FMemoryAllocationStatsV4.Diff(Old.MemoryAllocationStats4, New.MemoryAllocationStats4); ResultSnapshot.StreamIndex = New.StreamIndex; ResultSnapshot.bIsDiffResult = true; ResultSnapshot.AllocationMaxSize = New.AllocationMaxSize - Old.AllocationMaxSize; ResultSnapshot.AllocationSize = New.AllocationSize - Old.AllocationSize; ResultSnapshot.CurrentTime = 0; ResultSnapshot.ElapsedTime = New.CurrentTime - Old.CurrentTime; ResultSnapshot.FrameNumber = New.FrameNumber - Old.FrameNumber; ResultSnapshot.LoadedLevels = New.LoadedLevels; // These lists are guaranteed to be sorted by callstack index. List <FCallStackAllocationInfo> OldActiveCallStackList = Old.ActiveCallStackList; List <FCallStackAllocationInfo> NewActiveCallStackList = New.ActiveCallStackList; List <FCallStackAllocationInfo> ResultActiveCallStackList = new List <FCallStackAllocationInfo>(FStreamInfo.GlobalInstance.CallStackArray.Count); int OldIndex = 0; int NewIndex = 0; while (true) { FCallStackAllocationInfo OldAllocInfo = OldActiveCallStackList[OldIndex]; FCallStackAllocationInfo NewAllocInfo = NewActiveCallStackList[NewIndex]; if (OldAllocInfo.CallStackIndex == NewAllocInfo.CallStackIndex) { long ResultSize = NewAllocInfo.Size - OldAllocInfo.Size; int ResultCount = NewAllocInfo.Count - OldAllocInfo.Count; if (ResultSize != 0 || ResultCount != 0) { ResultActiveCallStackList.Add(new FCallStackAllocationInfo(ResultSize, NewAllocInfo.CallStackIndex, ResultCount)); } OldIndex++; NewIndex++; } else if (OldAllocInfo.CallStackIndex > NewAllocInfo.CallStackIndex) { ResultActiveCallStackList.Add(NewAllocInfo); NewIndex++; } else // OldAllocInfo.CallStackIndex < NewAllocInfo.CallStackIndex { ResultActiveCallStackList.Add(new FCallStackAllocationInfo(-OldAllocInfo.Size, OldAllocInfo.CallStackIndex, -OldAllocInfo.Count)); OldIndex++; } if (OldIndex >= OldActiveCallStackList.Count) { for ( ; NewIndex < NewActiveCallStackList.Count; NewIndex++) { ResultActiveCallStackList.Add(NewActiveCallStackList[NewIndex]); } break; } if (NewIndex >= NewActiveCallStackList.Count) { for ( ; OldIndex < OldActiveCallStackList.Count; OldIndex++) { ResultActiveCallStackList.Add(OldActiveCallStackList[OldIndex]); } break; } } // Check that list was correctly constructed. for (int CallstackIndex = 0; CallstackIndex < ResultActiveCallStackList.Count - 1; CallstackIndex++) { Debug.Assert(ResultActiveCallStackList[CallstackIndex].CallStackIndex < ResultActiveCallStackList[CallstackIndex + 1].CallStackIndex); } ResultActiveCallStackList.TrimExcess(); ResultSnapshot.ActiveCallStackList = ResultActiveCallStackList; // Iterate over new lifetime callstack info and subtract previous one. for (int CallStackIndex = 0; CallStackIndex < New.LifetimeCallStackList.Count; CallStackIndex++) { ResultSnapshot.LifetimeCallStackList[CallStackIndex] = FCallStackAllocationInfo.Diff( New.LifetimeCallStackList[CallStackIndex], Old.LifetimeCallStackList[CallStackIndex]); } // Handle overall memory timeline if (New.OverallMemorySlice.Count > Old.OverallMemorySlice.Count) { ResultSnapshot.OverallMemorySlice = new List <FMemorySlice>(New.OverallMemorySlice); ResultSnapshot.OverallMemorySlice.RemoveRange(0, Old.OverallMemorySlice.Count); } else { ResultSnapshot.OverallMemorySlice = new List <FMemorySlice>(Old.OverallMemorySlice); ResultSnapshot.OverallMemorySlice.RemoveRange(0, New.OverallMemorySlice.Count); ResultSnapshot.OverallMemorySlice.Reverse(); } } return(ResultSnapshot); }
/// <summary> Creates a new copy of this class. </summary> public FMemoryAllocationStatsV3 DeepCopy() { FMemoryAllocationStatsV3 Copy = ( FMemoryAllocationStatsV3 )MemberwiseClone(); return(Copy); }
/// <summary> Returns a difference between old and new memory allocation stats. </summary> public static FMemoryAllocationStatsV3 Diff( FMemoryAllocationStatsV3 Old, FMemoryAllocationStatsV3 New ) { FMemoryAllocationStatsV3 Diff = new FMemoryAllocationStatsV3(); FieldInfo[] FieldInfos = typeof( FMemoryAllocationStatsV3 ).GetFields(); int PropertiesNum = FieldInfos.Length; for( int FieldIndex = 0; FieldIndex < PropertiesNum; FieldIndex++ ) { Int64 OldValue = (Int64)FieldInfos[ FieldIndex ].GetValue( Old ); Int64 NewValue = (Int64)FieldInfos[ FieldIndex ].GetValue( New ); FieldInfos[ FieldIndex ].SetValue( Diff, NewValue-OldValue ); } return Diff; }