Files
UnrealEngine/Engine/Source/Editor/DerivedDataWidgets/Private/DerivedDataInformation.cpp
2025-05-18 13:04:45 +08:00

234 lines
7.7 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "DerivedDataInformation.h"
#include "DerivedDataCacheUsageStats.h"
#include "DerivedDataCacheInterface.h"
#include "Settings/EditorProjectSettings.h"
#include "Settings/EditorSettings.h"
#include "ToolMenus.h"
#define LOCTEXT_NAMESPACE "DerivedDataEditor"
double FDerivedDataInformation::LastGetTime = 0;
double FDerivedDataInformation::LastPutTime = 0;
bool FDerivedDataInformation::bIsDownloading = false;
bool FDerivedDataInformation::bIsUploading = false;
FText FDerivedDataInformation::RemoteCacheWarningMessage;
ERemoteCacheState FDerivedDataInformation::RemoteCacheState= ERemoteCacheState::Unavailable;
static TArray<TSharedRef<const FDerivedDataCacheStatsNode>> GetCacheUsageStats()
{
PRAGMA_DISABLE_DEPRECATION_WARNINGS;
TSharedRef<FDerivedDataCacheStatsNode> RootUsage = GetDerivedDataCacheRef().GatherUsageStats();
PRAGMA_ENABLE_DEPRECATION_WARNINGS;
TArray<TSharedRef<const FDerivedDataCacheStatsNode>> LeafUsageStats;
RootUsage->ForEachDescendant([&LeafUsageStats](TSharedRef<const FDerivedDataCacheStatsNode> Node)
{
if (Node->Children.IsEmpty())
{
LeafUsageStats.Add(Node);
}
});
return LeafUsageStats;
}
double FDerivedDataInformation::GetCacheActivitySizeBytes(bool bGet, bool bLocal)
{
int64 TotalBytes = 0;
#if ENABLE_COOK_STATS
for (const TSharedRef<const FDerivedDataCacheStatsNode>& Usage : GetCacheUsageStats())
{
if (Usage->IsLocal() != bLocal)
{
continue;
}
for (const auto& KVP : Usage->UsageStats)
{
const FDerivedDataCacheUsageStats& Stats = KVP.Value;
if (bGet)
{
TotalBytes += Stats.GetStats.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Bytes);
}
else
{
TotalBytes += Stats.PutStats.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Bytes);
}
}
}
#endif // ENABLE_COOK_STATS
return (double)TotalBytes;
}
double FDerivedDataInformation::GetCacheActivityTimeSeconds(bool bGet, bool bLocal)
{
int64 TotalCycles = 0;
#if ENABLE_COOK_STATS
for (const TSharedRef<const FDerivedDataCacheStatsNode>& Usage : GetCacheUsageStats())
{
if (Usage->IsLocal() != bLocal)
{
continue;
}
for (const auto& KVP : Usage->UsageStats)
{
const FDerivedDataCacheUsageStats& Stats = KVP.Value;
if (bGet)
{
TotalCycles +=
(Stats.GetStats.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Cycles) +
Stats.GetStats.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Miss, FCookStats::CallStats::EStatType::Cycles));
TotalCycles +=
(Stats.PrefetchStats.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Cycles) +
Stats.PrefetchStats.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Miss, FCookStats::CallStats::EStatType::Cycles));
}
else
{
TotalCycles +=
(Stats.PutStats.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Cycles) +
Stats.PutStats.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Miss, FCookStats::CallStats::EStatType::Cycles));
}
}
}
#endif // ENABLE_COOK_STATS
return (double)TotalCycles * FPlatformTime::GetSecondsPerCycle();
}
bool FDerivedDataInformation::GetHasRemoteCache()
{
for (const TSharedRef<const FDerivedDataCacheStatsNode>& Usage : GetCacheUsageStats())
{
if (!Usage->IsLocal())
{
return true;
}
}
return false;
}
bool FDerivedDataInformation::GetHasZenCache()
{
for (const TSharedRef<const FDerivedDataCacheStatsNode>& Usage : GetCacheUsageStats())
{
if (Usage->GetCacheType().Equals(TEXT("Zen")))
{
return true;
}
}
return false;
}
bool FDerivedDataInformation::GetHasUnrealCloudCache()
{
for (const TSharedRef<const FDerivedDataCacheStatsNode>& Usage : GetCacheUsageStats())
{
if (Usage->GetCacheType().Equals(TEXT("Unreal Cloud DDC")))
{
return true;
}
}
return false;
}
void FDerivedDataInformation::UpdateRemoteCacheState()
{
RemoteCacheState = ERemoteCacheState::Unavailable;
if ( GetHasRemoteCache() )
{
const double OldLastGetTime = LastGetTime;
const double OldLastPutTime = LastPutTime;
LastGetTime = FDerivedDataInformation::GetCacheActivityTimeSeconds(/*bGet*/ true, /*bLocal*/ false);
LastPutTime = FDerivedDataInformation::GetCacheActivityTimeSeconds(/*bGet*/ false, /*bLocal*/ false);
if (OldLastGetTime != 0.0 && OldLastPutTime != 0.0)
{
bIsDownloading = OldLastGetTime != LastGetTime;
bIsUploading = OldLastPutTime != LastPutTime;
}
if (bIsUploading || bIsDownloading)
{
RemoteCacheState = ERemoteCacheState::Busy;
}
else
{
RemoteCacheState = ERemoteCacheState::Idle;
}
}
if (const UDDCProjectSettings* DDCProjectSettings = GetDefault<UDDCProjectSettings>(); DDCProjectSettings && DDCProjectSettings->EnableWarnings)
{
const UEditorSettings* EditorSettings = GetDefault<UEditorSettings>();
if (EditorSettings && EditorSettings->bEnableDDCNotifications)
{
if (DDCProjectSettings->RecommendEveryoneUseUnrealCloudDDC && EditorSettings->bNotifyUseUnrealCloudDDC && !GetHasUnrealCloudCache())
{
RemoteCacheState = ERemoteCacheState::Warning;
RemoteCacheWarningMessage = FText(LOCTEXT("UnrealCloudDDCWarning", "It is recommended that you use Unreal Cloud DDC.\nDisable this notification in the settings."));
}
else if (DDCProjectSettings->RecommendEveryoneSetupAGlobalLocalDDCPath && EditorSettings->bNotifySetupDDCPath && EditorSettings->GlobalLocalDDCPath.Path.IsEmpty())
{
RemoteCacheState = ERemoteCacheState::Warning;
RemoteCacheWarningMessage = FText(LOCTEXT("GlobalLocalDDCPathWarning", "It is recommended that you set up a valid Global Local DDC Path.\nDisable this notification or set up a valid Global Local DDC Path in the settings."));
}
else if (DDCProjectSettings->RecommendEveryoneSetupAGlobalSharedDDCPath && EditorSettings->bNotifySetupDDCPath && EditorSettings->GlobalSharedDDCPath.Path.IsEmpty())
{
RemoteCacheState = ERemoteCacheState::Warning;
RemoteCacheWarningMessage = FText(LOCTEXT("GlobalSharedDDCPathWarning", "It is recommended that you set up a valid Global Shared DDC Path.\nDisable this notification or set up a valid Global Shared DDC Path in the settings."));
}
else if (DDCProjectSettings->RecommendEveryoneEnableS3DDC && EditorSettings->bNotifyEnableS3DD && !EditorSettings->bEnableS3DDC)
{
RemoteCacheState = ERemoteCacheState::Warning;
RemoteCacheWarningMessage = FText(LOCTEXT("AWSS3CacheEnabledWarning", "It is recommended that you enable the AWS S3 Cache.\nDisable this notification or enable the AWS S3 Cache in the settings."));
}
else if (DDCProjectSettings->RecommendEveryoneSetupAGlobalS3DDCPath && EditorSettings->bNotifySetupDDCPath && EditorSettings->GlobalS3DDCPath.Path.IsEmpty())
{
RemoteCacheState = ERemoteCacheState::Warning;
RemoteCacheWarningMessage = FText(LOCTEXT("S3GloblaLocalPathWarning", "It is recommended that you set up a valid Global Local S3 DDC Path.\nDisable this notification or set up a valid Global Local S3 DDC Path in the settings."));
}
}
}
}
FText FDerivedDataInformation::GetRemoteCacheStateAsText()
{
switch (FDerivedDataInformation::GetRemoteCacheState())
{
case ERemoteCacheState::Idle:
{
return FText(LOCTEXT("DDCStateIdle","Idle"));
}
case ERemoteCacheState::Busy:
{
return FText(LOCTEXT("DDCStateBusy", "Busy"));
}
case ERemoteCacheState::Unavailable:
{
return FText(LOCTEXT("DDCStateUnavailable", "Unavailable"));
}
default:
case ERemoteCacheState::Warning:
{
return FText(LOCTEXT("DDCStateWarning", "Warning"));
}
}
}
#undef LOCTEXT_NAMESPACE