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; }
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; }