Files
UnrealEngineUWP/Engine/Source/Developer/Profiler/Private/ProfilerStream.cpp
Robert Manuszewski 18e2561ceb Copying //UE4/Dev-Core to //UE4/Main
==========================
MAJOR FEATURES + CHANGES
==========================

Change 2836261 on 2016/01/20 by Robert.Manuszewski@Robert.Manuszewski_NCL_Stream1

	Flush FAsyncPackage cache after pre-load to reduce peak memory usage when async loading (5.5-10x).

Change 2828630 on 2016/01/14 by Robert.Manuszewski@Robert.Manuszewski_NCL_Stream1

	Adding debug code to catch memory stomps in the async loading buffers that's independent from mallocstomp allocator. Changed the signature of PageProtect functions to be able to read-only protect memory.

Change 2816129 on 2016/01/05 by Steve.Robb@Dev-Core

	Fixes for Realloc and alignment logic which caused redundant reallocations and incorrect binning.

Change 2821054 on 2016/01/08 by Steve.Robb@Dev-Core

	Further Realloc savings when realigning within a block.

Change 2806820 on 2015/12/17 by Steve.Robb@Dev-Core

	New AlignDown function, like Align, but which rounds a value/pointer down to the next alignment instead of up.

Change 2806816 on 2015/12/17 by Steve.Robb@Dev-Core

	Sort UHT modules by type to improve iteration times in conjunction with makefiles.

Change 2823235 on 2016/01/11 by Steve.Robb@Dev-Core

	UHT error messages about missing GENERATED_BODY() macros updated to represent intended use.

Change 2806815 on 2015/12/17 by Steve.Robb@Dev-Core

	Module types split into Game and Engine runtime versions.

Change 2833809 on 2016/01/19 by Robert.Manuszewski@Robert.Manuszewski_NCL_Stream1

	StaticLoadObject will now respect LOAD_NoRedirects flag.

Change 2811194 on 2015/12/22 by Bob.Tellez@Z2434_DevCore

	#UE4 Prevent loading packages that have a newer LegacyFileVersion since serialization for FCustomVersion is not forward compatible. UE-24443

Change 2806818 on 2015/12/17 by Steve.Robb@Dev-Core

	Removal of stats from MallocBinned2, to be readded later.

Change 2807069 on 2015/12/17 by Steve.Robb@Dev-Core

	Clarification of some bucket hashing terminology.

Change 2815117 on 2016/01/04 by Steve.Robb@Dev-Core

	Fix for a missing root build path on game modules.

Change 2815673 on 2016/01/05 by Steve.Robb@Dev-Core

	Move FMalloc verification into a proxy object.

Change 2822873 on 2016/01/11 by Steve.Robb@Dev-Core

	Fixes to off-by-one errors and removal of BinnedSizeLimit (assumed to be the same as MAX_POOLED_ALLOCATION_SIZE after OBO fix).

Change 2822923 on 2016/01/11 by Steve.Robb@Dev-Core

	Simplification of MemSizeToPoolTable indexing.

Change 2824974 on 2016/01/12 by Steve.Robb@Dev-Core

	Assert fixed.
	AllocateBlockFromPool's return value made debuggable.

Change 2825241 on 2016/01/12 by Steve.Robb@Dev-Core

	UHT now returns an error code on a warning when -warningsaserrors is specified.

Change 2825291 on 2016/01/12 by Steve.Robb@Dev-Core

	WarningsAsErrors enabled on UHT, after disabling the hardcoded behavior in CL# 2825241.

Change 2829846 on 2016/01/15 by Steve.Robb@Dev-Core

	GitHub #1938 - wrong Max value of enum is used during net serialization

Change 2829914 on 2016/01/15 by Robert.Manuszewski@Robert.Manuszewski_NCL_Stream1

	Reduce the amount of memory allocated for async cache buffers when guarding against memory stomps.

Change 2829988 on 2016/01/15 by Steve.Robb@Dev-Core

	Generalized large pool allocations.
	More redundancy removed.

Change 2831935 on 2016/01/18 by Chris.Wood@Chris.Wood.StreamB

	Added UserActivity property to crash description in CRP and CR website.
	[OR-12043] - Phone Home where crashes occur - pass context info to Crash Reporter

	DB column added to db-09 by ColinR matching this change.
	Published to server on Jan 18th 2016

Change 2834003 on 2016/01/19 by Chris.Wood@Chris.Wood.StreamB

	Added Linux to normal callstack parsing code on CR website
	[UE-25527] - Linux CrashReporter is missing information

	Published to server on Jan 19th 2016

Change 2835466 on 2016/01/20 by Joe.Conley@Joe.Conley_EGJWD5708_Dev-Core-Minimal

	Fix issue for cancelling package loads when there are still packages queued.  Call their PackageLoadedDelegate with a "Cancelled" result.

	Should solve remaining issue with UE-24062 - "Calling CancelAsyncLoading triggers an assert in FAsyncPackage::DetachLinker()"
	- (ULevelStreaming::AsyncLevelLoadComplete was not being called if packages were still queued when cancel was issued)

Change 2836803 on 2016/01/20 by Chris.Wood@Chris.Wood.StreamB

	CrashReportWebsite - fix exception thrown when parsing certain callstack formats

Change 2837952 on 2016/01/21 by Robert.Manuszewski@Robert.Manuszewski_NCL_Stream1

	Changing FAsyncIORequest to be stored as reference when cancelling IO requests to improve performance.

Change 2838289 on 2016/01/21 by Robert.Manuszewski@Robert.Manuszewski_NCL_Stream1

[CL 2845588 by Robert Manuszewski in Main branch]
2016-01-27 12:09:53 -05:00

171 lines
7.2 KiB
C++

// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
#include "ProfilerPrivatePCH.h"
/*-----------------------------------------------------------------------------
FProfilerUIStream
-----------------------------------------------------------------------------*/
void FProfilerUIStream::GenerateUIStream( const FProfilerStream& ProfilerStream, const double StartTimeMS, const double EndTimeMS, const double ZoomFactorX, const double NumMillisecondsPerWindow, const double NumPixelsPerMillisecond, const double NumMillisecondsPerSample )
{
//SCOPE_LOG_TIME_FUNC();
// Just copy the data for now.
const FIntPoint FramesIndices = ProfilerStream.GetFramesIndicesForTimeRange( StartTimeMS, EndTimeMS );
const double FrameTimeRangeMS = EndTimeMS - StartTimeMS;
const double WindowWidth = NumMillisecondsPerWindow*NumPixelsPerMillisecond;
// Preallocate nodes for threads.
ThreadNodes.Reset(ProfilerStream.GetNumThreads());
if( true || NumMillisecondsPerWindow >= FrameTimeRangeMS )
{
// Just copy the data.
const int32 NumFrames = ProfilerStream.GetNumFrames();
const int32 MaxFrameIndex = FMath::Min( FramesIndices.Y + 1, NumFrames - 1 );
for( int32 FrameIndex = FramesIndices.X; FrameIndex < MaxFrameIndex; ++FrameIndex )
{
const FProfilerFrame* ProfilerFrame = ProfilerStream.GetProfilerFrame( FrameIndex );
// Thread nodes.
const int32 NumThreads = ProfilerFrame->Root->Children.Num();
for( int32 ThreadIndex = 0; ThreadIndex < NumThreads; ++ThreadIndex )
{
FProfilerUIStackNode* ThreadUIStackNode = new FProfilerUIStackNode( ProfilerFrame->Root->Children[ThreadIndex], FProfilerUIStackNode::THREAD_NODE_INDEX, FProfilerUIStackNode::THREAD_NODE_INDEX, FrameIndex );
ThreadUIStackNode->InitializeUIData( NumMillisecondsPerWindow, NumPixelsPerMillisecond, NumMillisecondsPerSample );
ThreadNodes.Add( ThreadUIStackNode );
CombineOrSet( ThreadUIStackNode, *ProfilerFrame->Root->Children[ThreadIndex], ThreadIndex*DEFAULT_VISIBLE_THREAD_DEPTH, NumMillisecondsPerWindow, NumPixelsPerMillisecond, NumMillisecondsPerSample );
}
}
}
else
{
// #Profiler: 2014-04-28 Combining profiler frames doesn't make sense at this moment
// At this scale we may want to switch into line graph or something?
}
// #Profiler: 2014-04-25 MAX_THREAD_DEPTH;
LinearizeStream();
}
void FProfilerUIStream::CombineOrSet( FProfilerUIStackNode* ParentUIStackNode, const FProfilerStackNode& ProfilerStackNode, int32 GlobalNodeDepth, const double NumMillisecondsPerWindow, const double NumPixelsPerMillisecond, const double NumMillisecondsPerSample )
{
const int32 ThreadIndex = GlobalNodeDepth / DEFAULT_VISIBLE_THREAD_DEPTH;
const int32 ThreadNodeDepth = GlobalNodeDepth % DEFAULT_VISIBLE_THREAD_DEPTH;
const int32 NumChildren = ProfilerStackNode.Children.Num();
const int32 FrameIndex = ProfilerStackNode.FrameIndex;
if( NumChildren > 0 )
{
FProfilerStackNode* FirstProfilerChildNode = nullptr;
bool bLookingForChildToCombine = false;
TArray<const FProfilerStackNode*> OriginalStackNodes;
for( int32 ChildIndex = 0; ChildIndex < NumChildren; ++ChildIndex )
{
if( bLookingForChildToCombine )
{
const FProfilerStackNode* NextProfilerChildNode = ProfilerStackNode.Children[ChildIndex];
const bool bNeedsToBeCombined = NextProfilerChildNode->GetDurationMS() < NumMillisecondsPerSample;
// The next node can be displayed in the UI, add it and the previous one as the combined.
if( !bNeedsToBeCombined )
{
// Combine child nodes into one node.
{
FProfilerUIStackNode* ProfilerUIStackNode = new FProfilerUIStackNode( OriginalStackNodes, OriginalStackNodes.Num(), GlobalNodeDepth, ThreadIndex, FrameIndex );
ProfilerUIStackNode->InitializeUIData( NumMillisecondsPerWindow, NumPixelsPerMillisecond, NumMillisecondsPerSample );
ParentUIStackNode->Children.Add( ProfilerUIStackNode );
bLookingForChildToCombine = false;
OriginalStackNodes.Reset();
}
// Add the next node as a single node.
{
FProfilerUIStackNode* ProfilerUIStackNode = new FProfilerUIStackNode( NextProfilerChildNode, GlobalNodeDepth, ThreadIndex, FrameIndex );
ProfilerUIStackNode->InitializeUIData( NumMillisecondsPerWindow, NumPixelsPerMillisecond, NumMillisecondsPerSample );
ParentUIStackNode->Children.Add( ProfilerUIStackNode );
// Check the call stack depth.
if( ThreadNodeDepth != DEFAULT_VISIBLE_THREAD_DEPTH - 1 )
{
CombineOrSet( ProfilerUIStackNode, *NextProfilerChildNode, GlobalNodeDepth + 1, NumMillisecondsPerWindow, NumPixelsPerMillisecond, NumMillisecondsPerSample );
}
else
{
// Mark this node as culled.
ProfilerUIStackNode->MarkAsCulled();
}
}
continue;
}
// We need to combine a few child nodes into one node.
const double CombinedDurationMS = NextProfilerChildNode->CycleCounterEndTimeMS - FirstProfilerChildNode->CycleCounterStartTimeMS;
OriginalStackNodes.Add( NextProfilerChildNode );
const bool bCanBeCombined = CombinedDurationMS > NumMillisecondsPerSample;
if( bCanBeCombined )
{
// Combine child nodes into one node.
FProfilerUIStackNode* ProfilerUIStackNode = new FProfilerUIStackNode( OriginalStackNodes, OriginalStackNodes.Num(), GlobalNodeDepth, ThreadIndex, FrameIndex );
ProfilerUIStackNode->InitializeUIData( NumMillisecondsPerWindow, NumPixelsPerMillisecond, NumMillisecondsPerSample );
ParentUIStackNode->Children.Add( ProfilerUIStackNode );
bLookingForChildToCombine = false;
OriginalStackNodes.Reset();
}
continue;
}
FirstProfilerChildNode = ProfilerStackNode.Children[ChildIndex];
const bool bNeedsToBeCombined = FirstProfilerChildNode->GetDurationMS() < NumMillisecondsPerSample;
if( !bNeedsToBeCombined && !bLookingForChildToCombine )
{
// We have a sample that can be displayed in the UI, add it.
FProfilerUIStackNode* ProfilerUIStackNode = new FProfilerUIStackNode( FirstProfilerChildNode, GlobalNodeDepth, ThreadIndex, FrameIndex );
ProfilerUIStackNode->InitializeUIData( NumMillisecondsPerWindow, NumPixelsPerMillisecond, NumMillisecondsPerSample );
ParentUIStackNode->Children.Add( ProfilerUIStackNode );
// Check the call stack depth.
if( ThreadNodeDepth != DEFAULT_VISIBLE_THREAD_DEPTH - 1 )
{
CombineOrSet( ProfilerUIStackNode, *FirstProfilerChildNode, GlobalNodeDepth + 1, NumMillisecondsPerWindow, NumPixelsPerMillisecond, NumMillisecondsPerSample );
}
else
{
// Mark this node as culled.
ProfilerUIStackNode->MarkAsCulled();
}
}
else
{
bLookingForChildToCombine = true;
OriginalStackNodes.Add( FirstProfilerChildNode );
}
}
// We are out of the loop, but still need to combine children even if not visible.
if( bLookingForChildToCombine )
{
// Combine child nodes into one node.
{
FProfilerUIStackNode* ProfilerUIStackNode = new FProfilerUIStackNode( OriginalStackNodes, OriginalStackNodes.Num(), GlobalNodeDepth, ThreadIndex, FrameIndex );
ProfilerUIStackNode->InitializeUIData( NumMillisecondsPerWindow, NumPixelsPerMillisecond, NumMillisecondsPerSample );
ParentUIStackNode->Children.Add( ProfilerUIStackNode );
bLookingForChildToCombine = false;
OriginalStackNodes.Reset();
}
}
}
}