Files
UnrealEngineUWP/Engine/Source/Editor/UnrealEd/Private/Cooker/CookProfiling.cpp
Matt Peters c21db29e38 Cooker Stats: Fix the "Packages Cooked" stat line to use the number of packages cooked rather than the number of packages multiplied by the number of platforms.
#rb Devin.Doucette
#rnx
#preflight 628d0348c97e4beea3a51802

[CL 20350856 by Matt Peters in ue5-main branch]
2022-05-24 13:04:27 -04:00

201 lines
5.3 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "CookProfiling.h"
#include "CookOnTheSide/CookLog.h"
#if OUTPUT_COOKTIMING || ENABLE_COOK_STATS
#include "ProfilingDebugging/ScopedTimers.h"
#endif
#if OUTPUT_COOKTIMING
#include <Containers/AllocatorFixedSizeFreeList.h>
struct FHierarchicalTimerInfo
{
public:
FHierarchicalTimerInfo(const FHierarchicalTimerInfo& InTimerInfo) = delete;
FHierarchicalTimerInfo(FHierarchicalTimerInfo&& InTimerInfo) = delete;
explicit FHierarchicalTimerInfo(const char* InName, uint16 InId)
: Id(InId)
, Name(InName)
{
}
~FHierarchicalTimerInfo()
{
ClearChildren();
}
void ClearChildren()
{
for (FHierarchicalTimerInfo* Child = FirstChild; Child;)
{
FHierarchicalTimerInfo* NextChild = Child->NextSibling;
DestroyAndFree(Child);
Child = NextChild;
}
FirstChild = nullptr;
}
FHierarchicalTimerInfo* GetChild(int InId, const char* InName)
{
for (FHierarchicalTimerInfo* Child = FirstChild; Child;)
{
if (Child->Id == InId)
return Child;
Child = Child->NextSibling;
}
FHierarchicalTimerInfo* Child = AllocNew(InName, InId);
Child->NextSibling = FirstChild;
FirstChild = Child;
return Child;
}
uint32 HitCount = 0;
uint16 Id = 0;
bool IncrementDepth = true;
double Length = 0;
const char* Name;
FHierarchicalTimerInfo* FirstChild = nullptr;
FHierarchicalTimerInfo* NextSibling = nullptr;
private:
static FHierarchicalTimerInfo* AllocNew(const char* InName, uint16 InId);
static void DestroyAndFree(FHierarchicalTimerInfo* InPtr);
};
static FHierarchicalTimerInfo RootTimerInfo("Root", 0);
static FHierarchicalTimerInfo* CurrentTimerInfo = &RootTimerInfo;
static TAllocatorFixedSizeFreeList<sizeof(FHierarchicalTimerInfo), 256> TimerInfoAllocator;
FHierarchicalTimerInfo* FHierarchicalTimerInfo::AllocNew(const char* InName, uint16 InId)
{
return new(TimerInfoAllocator.Allocate()) FHierarchicalTimerInfo(InName, InId);
}
void FHierarchicalTimerInfo::DestroyAndFree(FHierarchicalTimerInfo* InPtr)
{
InPtr->~FHierarchicalTimerInfo();
TimerInfoAllocator.Free(InPtr);
}
FScopeTimer::FScopeTimer(int InId, const char* InName, bool IncrementScope /*= false*/ )
{
checkSlow(IsInGameThread());
HierarchyTimerInfo = CurrentTimerInfo->GetChild(InId, InName);
HierarchyTimerInfo->IncrementDepth = IncrementScope;
PrevTimerInfo = CurrentTimerInfo;
CurrentTimerInfo = HierarchyTimerInfo;
}
void FScopeTimer::Start()
{
if (StartTime)
{
return;
}
StartTime = FPlatformTime::Cycles64();
}
void FScopeTimer::Stop()
{
if (!StartTime)
{
return;
}
HierarchyTimerInfo->Length += FPlatformTime::ToSeconds64(FPlatformTime::Cycles64() - StartTime);
++HierarchyTimerInfo->HitCount;
StartTime = 0;
}
FScopeTimer::~FScopeTimer()
{
Stop();
check(CurrentTimerInfo == HierarchyTimerInfo);
CurrentTimerInfo = PrevTimerInfo;
}
void OutputHierarchyTimers(const FHierarchicalTimerInfo* TimerInfo, int32 Depth)
{
FString TimerName(TimerInfo->Name);
static const TCHAR LeftPad[] = TEXT(" ");
const SIZE_T PadOffset = FMath::Max<int>(UE_ARRAY_COUNT(LeftPad) - 1 - Depth * 2, 0);
UE_LOG(LogCook, Display, TEXT(" %s%s: %.3fs (%u)"), &LeftPad[PadOffset], *TimerName, TimerInfo->Length, TimerInfo->HitCount);
// We need to print in reverse order since the child list begins with the most recently added child
TArray<const FHierarchicalTimerInfo*> Stack;
for (const FHierarchicalTimerInfo* Child = TimerInfo->FirstChild; Child; Child = Child->NextSibling)
{
Stack.Add(Child);
}
const int32 ChildDepth = Depth + TimerInfo->IncrementDepth;
for (size_t i = Stack.Num(); i > 0; --i)
{
OutputHierarchyTimers(Stack[i - 1], ChildDepth);
}
}
void OutputHierarchyTimers()
{
UE_LOG(LogCook, Display, TEXT("Hierarchy Timer Information:"));
OutputHierarchyTimers(&RootTimerInfo, 0);
}
void ClearHierarchyTimers()
{
RootTimerInfo.ClearChildren();
}
#endif
#if ENABLE_COOK_STATS
namespace DetailedCookStats
{
double TickCookOnTheSideTimeSec = 0.0;
double TickCookOnTheSideLoadPackagesTimeSec = 0.0;
double TickCookOnTheSideResolveRedirectorsTimeSec = 0.0;
double TickCookOnTheSideSaveCookedPackageTimeSec = 0.0;
double TickCookOnTheSideBeginPrepareSaveTimeSec = 0.0;
double TickCookOnTheSideFinishPrepareSaveTimeSec = 0.0;
double GameCookModificationDelegateTimeSec = 0.0;
// Stats tracked through FAutoRegisterCallback
int32 PeakRequestQueueSize = 0;
int32 PeakLoadQueueSize = 0;
int32 PeakSaveQueueSize = 0;
uint32 NumPreloadedDependencies = 0;
uint32 NumPackagesIterativelySkipped = 0;
uint32 NumPackagesSavedForCook = 0;
FCookStatsManager::FAutoRegisterCallback RegisterCookOnTheFlyServerStats([](FCookStatsManager::AddStatFuncRef AddStat)
{
AddStat(TEXT("Package.Load"), FCookStatsManager::CreateKeyValueArray(TEXT("NumPreloadedDependencies"), NumPreloadedDependencies));
AddStat(TEXT("Package.Save"), FCookStatsManager::CreateKeyValueArray(TEXT("NumPackagesIterativelySkipped"), NumPackagesIterativelySkipped));
AddStat(TEXT("CookOnTheFlyServer"), FCookStatsManager::CreateKeyValueArray(TEXT("PeakRequestQueueSize"), PeakRequestQueueSize));
AddStat(TEXT("CookOnTheFlyServer"), FCookStatsManager::CreateKeyValueArray(TEXT("PeakLoadQueueSize"), PeakLoadQueueSize));
AddStat(TEXT("CookOnTheFlyServer"), FCookStatsManager::CreateKeyValueArray(TEXT("PeakSaveQueueSize"), PeakSaveQueueSize));
});
}
#endif