int32 FServiceConnection::FindOrAddThread(const FStatNameAndInfo& Thread)
{
	SCOPE_CYCLE_COUNTER(STAT_PC_FindOrAddThread);

	const FName LongName = Thread.GetRawName();
	int32* const ThreadIDPtr = ThreadNameArray.Find( LongName );
	int32 ThreadID = ThreadIDPtr != nullptr ? *ThreadIDPtr : -1;
	if (!ThreadIDPtr)
	{
		// meta data has been updated
		CurrentData.MetaDataUpdated = true;

		// get the thread description
		FString Desc;
		Thread.GetDescription(Desc);

		// Extract out the thread id and add to the descriptions
		FString ID = Desc.Replace(TEXT("Thread_"), TEXT(""));
		ID = ID.Replace(TEXT("_0"), TEXT(""));
		ThreadID = FParse::HexNumber(*ID);
		ThreadNameArray.Add(LongName, ThreadID);

		// add to the meta data
		FScopeLock ScopeLock(&CriticalSection);
		MetaData.ThreadDescriptions.Add(ThreadID, Thread.GetShortName().ToString());
	}

	return ThreadID;
}
예제 #2
0
void FStats::AdvanceFrame( bool bDiscardCallstack, const FOnAdvanceRenderingThreadStats& AdvanceRenderingThreadStatsDelegate /*= FOnAdvanceRenderingThreadStats()*/ )
{
#if STATS
	check( IsInGameThread() );
	static int32 MasterDisableChangeTagStartFrame = -1;
	FPlatformAtomics::InterlockedIncrement(&GameThreadStatsFrame);

	int64 Frame = GameThreadStatsFrame;
	if( bDiscardCallstack )
	{
		FThreadStats::FrameDataIsIncomplete(); // we won't collect call stack stats this frame
	}
	if( MasterDisableChangeTagStartFrame == -1 )
	{
		MasterDisableChangeTagStartFrame = FThreadStats::MasterDisableChangeTag();
	}
	if( !FThreadStats::IsCollectingData() || MasterDisableChangeTagStartFrame != FThreadStats::MasterDisableChangeTag() )
	{
		Frame = -GameThreadStatsFrame; // mark this as a bad frame
	}

	// Update the seconds per cycle.
	SET_FLOAT_STAT( STAT_SecondsPerCycle, FPlatformTime::GetSecondsPerCycle() );

	static FStatNameAndInfo Adv( NAME_AdvanceFrame, "", "", TEXT( "" ), EStatDataType::ST_int64, true, false );
	FThreadStats::AddMessage( Adv.GetEncodedName(), EStatOperation::AdvanceFrameEventGameThread, Frame ); // we need to flush here if we aren't collecting stats to make sure the meta data is up to date
	if( FPlatformProperties::IsServerOnly() )
	{
		FThreadStats::AddMessage( Adv.GetEncodedName(), EStatOperation::AdvanceFrameEventRenderThread, Frame ); // we need to flush here if we aren't collecting stats to make sure the meta data is up to date
	}

	if( AdvanceRenderingThreadStatsDelegate.IsBound() )
	{
		AdvanceRenderingThreadStatsDelegate.Execute( bDiscardCallstack, GameThreadStatsFrame, MasterDisableChangeTagStartFrame );
	}
	else
	{
		// There is no rendering thread, so this message is sufficient to make stats happy and don't leak memory.
		FThreadStats::AddMessage( Adv.GetEncodedName(), EStatOperation::AdvanceFrameEventRenderThread, Frame );
	}

	FThreadStats::ExplicitFlush( bDiscardCallstack );
	FThreadStats::WaitForStats();
	MasterDisableChangeTagStartFrame = FThreadStats::MasterDisableChangeTag();
#endif
}
int32 FServiceConnection::FindOrAddThread(const FStatNameAndInfo& Thread)
{
	SCOPE_CYCLE_COUNTER(STAT_PC_FindOrAddThread);

	// The description of a thread group contains the thread id
	const FString Desc = Thread.GetDescription();
	const uint32 ThreadID = FStatsUtils::ParseThreadID( Desc );

	const FName ShortName = Thread.GetShortName();

	// add to the meta data
	FScopeLock ScopeLock( &CriticalSection );
	const int32 OldNum = MetaData.ThreadDescriptions.Num();
	MetaData.ThreadDescriptions.Add( ThreadID, ShortName.ToString() );
	const int32 NewNum = MetaData.ThreadDescriptions.Num();

	// meta data has been updated
	CurrentData.MetaDataUpdated = CurrentData.MetaDataUpdated || OldNum != NewNum;

	return ThreadID;
}
void FServiceConnection::Initialize( const FProfilerServiceAuthorize2& Message, const IMessageContextRef& Context )
{
#if STATS
	ServiceAddress = Context->GetSender();
	InstanceId = Message.InstanceId;
	CurrentData.Frame = 0;

	// add the supplied meta data
	FArrayReader ArrayReader(true);
	ArrayReader.Append(Message.Data);

	MetaData.CriticalSection = &CriticalSection;
	int64 Size = ArrayReader.TotalSize();

	// read in the magic, at some point may need to know what it actually is
	uint32 Magic = 0;
	ArrayReader << Magic;

	// read in the data
	TArray<FStatMessage> StatMessages;
	{
		SCOPE_CYCLE_COUNTER(STAT_PC_ReadStatMessages);
		while(ArrayReader.Tell() < Size)
		{
			// read the message
			new (StatMessages) FStatMessage(Stream.ReadMessage(ArrayReader));
		}
		static FStatNameAndInfo Adv(NAME_AdvanceFrame, "", TEXT(""), EStatDataType::ST_int64, true, false);
		new (StatMessages) FStatMessage(Adv.GetEncodedName(), EStatOperation::AdvanceFrameEventGameThread, 1LL, false);
	}

	// generate a thread state from the data
	{
		SCOPE_CYCLE_COUNTER(STAT_PC_AddStatMessages);
		CurrentThreadState.AddMessages(StatMessages);
	}

	UpdateMetaData();
#endif
}
int32 FServiceConnection::FindOrAddStat( const FStatNameAndInfo& StatNameAndInfo, uint32 StatType)
{
	SCOPE_CYCLE_COUNTER(STAT_PC_FindOrAddStat);
	const FName LongName = StatNameAndInfo.GetRawName();
	int32* const StatIDPtr = LongNameToStatID.Find( LongName );
	int32 StatID = StatIDPtr != nullptr ? *StatIDPtr : -1;

	if (!StatIDPtr)
	{
		// meta data has been updated
		CurrentData.MetaDataUpdated = true;

		const FName StatName = StatNameAndInfo.GetShortName();
		FName GroupName = StatNameAndInfo.GetGroupName();
		const FString Description = StatNameAndInfo.GetDescription();

		// do some special stats first
		if (StatName == TEXT("STAT_FrameTime"))
		{
			StatID = LongNameToStatID.Add(LongName, 2);
		}
		else if (StatName == FStatConstants::NAME_ThreadRoot)
		{
			StatID = LongNameToStatID.Add(LongName, 1);
			GroupName = TEXT( "NoGroup" );
		}
		else
		{
			StatID = LongNameToStatID.Add(LongName, LongNameToStatID.Num()+10);
		}
		check(StatID != -1);

		// add a new stat description to the meta data
		FStatDescription StatDescription;
		StatDescription.ID = StatID;
		StatDescription.Name = !Description.IsEmpty() ? Description : StatName.ToString();
		if( StatDescription.Name.Contains( TEXT("STAT_") ) )
		{
			StatDescription.Name = StatDescription.Name.RightChop(FString(TEXT("STAT_")).Len());
		}
		StatDescription.StatType = StatType;

		if( GroupName == NAME_None && Stream.Header.Version == EStatMagicNoHeader::NO_VERSION )
		{	
			// @todo Add more ways to group the stats.
			const int32 Thread_Pos = StatDescription.Name.Find( TEXT("Thread_") );
			const int32 _0Pos = StatDescription.Name.Find( TEXT("_0") );
			const bool bIsThread = Thread_Pos != INDEX_NONE && _0Pos > Thread_Pos;
			// Add a special group for all threads.
			if( bIsThread )
			{
				GroupName = TEXT("Threads");
			}
			// Add a special group for all objects.
			else
			{
				GroupName = TEXT("Objects");
			}
		}

		int32* const GroupIDPtr = GroupNameArray.Find( GroupName );
		int32 GroupID = GroupIDPtr != nullptr ? *GroupIDPtr : -1;
		if( !GroupIDPtr )
		{
			// add a new group description to the meta data
			GroupID = GroupNameArray.Add(GroupName, GroupNameArray.Num()+10);
			check( GroupID != -1 );

			FStatGroupDescription GroupDescription;
			GroupDescription.ID = GroupID;
			GroupDescription.Name = GroupName.ToString();
			GroupDescription.Name.RemoveFromStart(TEXT("STATGROUP_"));

			// add to the meta data
			FScopeLock ScopeLock(&CriticalSection);
			MetaData.GroupDescriptions.Add(GroupDescription.ID, GroupDescription);
		}
		{
			StatDescription.GroupID = GroupID;
			FScopeLock ScopeLock(&CriticalSection);
			MetaData.StatDescriptions.Add(StatDescription.ID, StatDescription);
		}
	}
	// return the stat id
	return StatID;
}