2019-12-26 15:32:37 -05:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
2019-06-03 15:32:00 -04:00
|
|
|
|
|
|
|
|
#include "TraceServices/Model/Threads.h"
|
|
|
|
|
#include "Model/ThreadsPrivate.h"
|
|
|
|
|
#include "Misc/ScopeLock.h"
|
|
|
|
|
#include "AnalysisServicePrivate.h"
|
|
|
|
|
#include "Common/StringStore.h"
|
|
|
|
|
|
2020-11-13 05:29:37 -04:00
|
|
|
namespace TraceServices
|
2019-06-03 15:32:00 -04:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
const FName FThreadProvider::ProviderName = "ThreadProvider";
|
|
|
|
|
|
|
|
|
|
FThreadProvider::FThreadProvider(IAnalysisSession& InSession)
|
|
|
|
|
: Session(InSession)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FThreadProvider::~FThreadProvider()
|
|
|
|
|
{
|
|
|
|
|
for (FThreadInfoInternal* Thread : SortedThreads)
|
|
|
|
|
{
|
|
|
|
|
delete Thread;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FThreadProvider::AddGameThread(uint32 Id)
|
|
|
|
|
{
|
2022-01-17 23:58:56 -05:00
|
|
|
const FString Name = FName(NAME_GameThread).GetPlainNameString();
|
2021-01-25 04:27:02 -04:00
|
|
|
AddThread(Id, *Name, EThreadPriority(-2));
|
2019-06-03 15:32:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FThreadProvider::AddThread(uint32 Id, const TCHAR* Name, EThreadPriority Priority)
|
|
|
|
|
{
|
|
|
|
|
Session.WriteAccessCheck();
|
|
|
|
|
|
|
|
|
|
FThreadInfoInternal* ThreadInfo;
|
|
|
|
|
if (!ThreadMap.Contains(Id))
|
|
|
|
|
{
|
|
|
|
|
ThreadInfo = new FThreadInfoInternal();
|
|
|
|
|
ThreadInfo->Id = Id;
|
|
|
|
|
ThreadInfo->FallbackSortOrder = SortedThreads.Num();
|
|
|
|
|
SortedThreads.Add(ThreadInfo);
|
|
|
|
|
ThreadMap.Add(Id, ThreadInfo);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ThreadInfo = ThreadMap[Id];
|
|
|
|
|
}
|
2020-08-11 01:36:57 -04:00
|
|
|
if (Name != nullptr)
|
|
|
|
|
{
|
2022-01-17 23:58:56 -05:00
|
|
|
if (Name[0] != 0)
|
|
|
|
|
{
|
|
|
|
|
ThreadInfo->Name = Session.StoreString(Name);
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-12 16:17:19 -04:00
|
|
|
if (!FCString::Strcmp(Name, TEXT("RHIThread"))) //-V1051
|
2020-09-24 00:43:27 -04:00
|
|
|
{
|
|
|
|
|
const TCHAR* GroupName = Session.StoreString(TEXT("Render"));
|
|
|
|
|
SetThreadGroup(Id, GroupName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ThreadInfo->PrioritySortOrder = GetPrioritySortOrder(Priority);
|
2020-08-11 01:36:57 -04:00
|
|
|
}
|
2019-06-03 15:32:00 -04:00
|
|
|
SortThreads();
|
|
|
|
|
++ModCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FThreadProvider::SetThreadPriority(uint32 Id, EThreadPriority Priority)
|
|
|
|
|
{
|
|
|
|
|
Session.WriteAccessCheck();
|
|
|
|
|
|
|
|
|
|
check(ThreadMap.Contains(Id));
|
|
|
|
|
FThreadInfoInternal* ThreadInfo = ThreadMap[Id];
|
2020-09-24 00:43:27 -04:00
|
|
|
ensure(ThreadInfo->PrioritySortOrder != -2);
|
2019-06-03 15:32:00 -04:00
|
|
|
ThreadInfo->PrioritySortOrder = GetPrioritySortOrder(Priority);
|
|
|
|
|
SortThreads();
|
|
|
|
|
++ModCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FThreadProvider::SetThreadGroup(uint32 Id, const TCHAR* GroupName)
|
|
|
|
|
{
|
|
|
|
|
Session.WriteAccessCheck();
|
|
|
|
|
|
|
|
|
|
check(ThreadMap.Contains(Id));
|
|
|
|
|
FThreadInfoInternal* ThreadInfo = ThreadMap[Id];
|
|
|
|
|
ThreadInfo->GroupName = GroupName;
|
|
|
|
|
ThreadInfo->GroupSortOrder = GetGroupSortOrder(GroupName);
|
|
|
|
|
SortThreads();
|
|
|
|
|
++ModCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FThreadProvider::EnumerateThreads(TFunctionRef<void(const FThreadInfo &)> Callback) const
|
|
|
|
|
{
|
|
|
|
|
Session.ReadAccessCheck();
|
|
|
|
|
|
|
|
|
|
for (const FThreadInfoInternal* Thread : SortedThreads)
|
|
|
|
|
{
|
|
|
|
|
FThreadInfo ThreadInfo;
|
|
|
|
|
ThreadInfo.Id = Thread->Id;
|
|
|
|
|
ThreadInfo.Name = Thread->Name;
|
|
|
|
|
ThreadInfo.GroupName = Thread->GroupName;
|
|
|
|
|
Callback(ThreadInfo);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-03 16:26:48 -04:00
|
|
|
const TCHAR* FThreadProvider::GetThreadName(uint32 ThreadId) const
|
|
|
|
|
{
|
|
|
|
|
Session.ReadAccessCheck();
|
|
|
|
|
|
|
|
|
|
const FThreadInfoInternal* const* FindIt = ThreadMap.Find(ThreadId);
|
|
|
|
|
if (!FindIt)
|
|
|
|
|
{
|
|
|
|
|
return TEXT("");
|
|
|
|
|
}
|
|
|
|
|
return (*FindIt)->Name;
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-03 15:32:00 -04:00
|
|
|
void FThreadProvider::SortThreads()
|
|
|
|
|
{
|
|
|
|
|
Algo::SortBy(SortedThreads, [](const FThreadInfoInternal* In) -> const FThreadInfoInternal&
|
|
|
|
|
{
|
|
|
|
|
return *In;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32 FThreadProvider::GetGroupSortOrder(const TCHAR* GroupName)
|
|
|
|
|
{
|
|
|
|
|
if (!GroupName)
|
|
|
|
|
{
|
|
|
|
|
return uint32(-1);
|
|
|
|
|
}
|
|
|
|
|
else if (!FCString::Strcmp(GroupName, TEXT("Render")))
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else if (!FCString::Strcmp(GroupName, TEXT("AsyncLoading")))
|
|
|
|
|
{
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if (!FCString::Strcmp(GroupName, TEXT("TaskGraphHigh")))
|
|
|
|
|
{
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
else if (!FCString::Strcmp(GroupName, TEXT("TaskGraphNormal")))
|
|
|
|
|
{
|
|
|
|
|
return 3;
|
|
|
|
|
}
|
|
|
|
|
else if (!FCString::Strcmp(GroupName, TEXT("TaskGraphLow")))
|
|
|
|
|
{
|
|
|
|
|
return 4;
|
|
|
|
|
}
|
|
|
|
|
else if (!FCString::Strcmp(GroupName, TEXT("LargeThreadPool")))
|
|
|
|
|
{
|
|
|
|
|
return 5;
|
|
|
|
|
}
|
|
|
|
|
else if (!FCString::Strcmp(GroupName, TEXT("ThreadPool")))
|
|
|
|
|
{
|
|
|
|
|
return 6;
|
|
|
|
|
}
|
|
|
|
|
else if (!FCString::Strcmp(GroupName, TEXT("BackgroundThreadPool")))
|
|
|
|
|
{
|
|
|
|
|
return 7;
|
|
|
|
|
}
|
|
|
|
|
else if (!FCString::Strcmp(GroupName, TEXT("IOThreadPool")))
|
|
|
|
|
{
|
|
|
|
|
return 8;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return GetTypeHash(GroupName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 18:40:00 -04:00
|
|
|
int32 FThreadProvider::GetPrioritySortOrder(EThreadPriority ThreadPriority)
|
2019-06-03 15:32:00 -04:00
|
|
|
{
|
|
|
|
|
switch (ThreadPriority)
|
|
|
|
|
{
|
|
|
|
|
case TPri_TimeCritical:
|
|
|
|
|
return 0;
|
|
|
|
|
case TPri_Highest:
|
|
|
|
|
return 1;
|
|
|
|
|
case TPri_AboveNormal:
|
|
|
|
|
return 2;
|
|
|
|
|
case TPri_Normal:
|
|
|
|
|
return 3;
|
|
|
|
|
case TPri_SlightlyBelowNormal:
|
|
|
|
|
return 4;
|
|
|
|
|
case TPri_BelowNormal:
|
|
|
|
|
return 5;
|
|
|
|
|
case TPri_Lowest:
|
|
|
|
|
return 6;
|
|
|
|
|
default:
|
2020-06-23 18:40:00 -04:00
|
|
|
return int32(ThreadPriority);
|
2019-06-03 15:32:00 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FThreadProvider::FThreadInfoInternal::operator<(const FThreadInfoInternal& Other) const
|
|
|
|
|
{
|
2020-06-23 18:40:00 -04:00
|
|
|
if (PrioritySortOrder < 0 || Other.PrioritySortOrder < 0)
|
|
|
|
|
{
|
|
|
|
|
return PrioritySortOrder < Other.PrioritySortOrder;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (GroupSortOrder == Other.GroupSortOrder)
|
|
|
|
|
{
|
|
|
|
|
if (PrioritySortOrder == Other.PrioritySortOrder)
|
|
|
|
|
{
|
|
|
|
|
return FallbackSortOrder < Other.FallbackSortOrder;
|
|
|
|
|
}
|
|
|
|
|
return PrioritySortOrder < Other.PrioritySortOrder;
|
|
|
|
|
}
|
|
|
|
|
return GroupSortOrder < Other.GroupSortOrder;
|
2019-06-03 15:32:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const IThreadProvider& ReadThreadProvider(const IAnalysisSession& Session)
|
|
|
|
|
{
|
|
|
|
|
return *Session.ReadProvider<IThreadProvider>(FThreadProvider::ProviderName);
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-13 05:29:37 -04:00
|
|
|
} // namespace TraceServices
|