Files
UnrealEngineUWP/Engine/Source/Developer/Virtualization/Private/VirtualizationManager.cpp

2171 lines
72 KiB
C++
Raw Normal View History

// Copyright Epic Games, Inc. All Rights Reserved.
#include "VirtualizationManager.h"
#include "HAL/IConsoleManager.h"
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
#include "HAL/PlatformTime.h"
#include "Logging/MessageLog.h"
#include "Misc/CommandLine.h"
#include "Misc/ConfigCacheIni.h"
#include "Misc/PackageName.h"
#include "Misc/PackagePath.h"
#include "Misc/Parse.h"
#include "Misc/Paths.h"
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
#include "Misc/ScopeLock.h"
Add a rehydration command to the stand alone virtualization tool, making it easier to reverse the effects of asset virtualization. Unlike previous processes, this one does not require that we load the package and will just manipulate the data storaged in the package trailer. #rb Sebastian.Nordgren #rnx #jira UE-156436 #preflight 62c287f9a3568e30664eb94f ### VA Standalone Tool - We now plan to add much more functionality to the tool than just virtualizing and submitting changelists, so to make this easier I am moving the tool towards a design where it should be fairly easy to add new functionality. - Added FCommand, which is a base class for adding new functionality, simple derive from FCommand and hook it up at the appropriate locations. -- In the future it should be possible for new command types to automatically register themselves to be initiated from the command line. There should be no need to edit UnrealVirtualizationToolApp to add a new command but this will be done as an additional work item. -- At the moment FCommand comes with a number of utility methods to call that cover some common source control commands. -- The original functionality has not yet been moved to the command system and so the code is a little bit weird at the moment. Updating older code to the new system will be done as an additional work item. - FProject/FPlugin have been moved to their own code files. ### Rehydrate Command - The rehydrate command will take a number of packages, check them out of source control and then attempt to virtualize them. - At the moment the chekout logic is fairly basic, we just check out every package supplied, we don't check if the package is virtualized or not yet. This can be improved in additional work items. Ideally by the end of command the only packages that we have checked out should also be rehydrated. - At the moment the command can either take a path of a specific package, a path of a directory to find packages in, or a changelist containing packages that should be rehydrated. - A cleint spec (workspace) can optionally be provided, but if not supplied we will attempt to find a client spec for which to check out the packages. - Currently we will check out the packages to the default change list. ### Rehydrate process - Added the rehydration process in it's own code files in the virtualization module. Like the virtualization process this is exposed in a public header file and no via the Core interface which means it is very specific to our module/implementation. - The process expects that the caller will have checked out any required packages from source control. It will treat being unable to update a package file as an error. - Added PackageUtils.h/.cpp and moved some of the generic code from the virtualization process code there so that it can be shared by the rehydration process. ### Misc Moving away from the using things like FPackagePath as that requires that the correct mount points have been registered for a project and at the moment (with the flakiness of FConfig*) it seems that the best idea would be to prefer absolute file paths where possible. [CL 20982284 by paul chipchase in ue5-main branch]
2022-07-07 06:54:33 -04:00
#include "PackageRehydrationProcess.h"
#include "Misc/ScopedSlowTask.h"
#include "PackageVirtualizationProcess.h"
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
#include "ProfilingDebugging/CookStats.h"
#include "VirtualizationFilterSettings.h"
#include "AnalyticsEventAttribute.h"
#include "Misc/MessageDialog.h"
#define LOCTEXT_NAMESPACE "Virtualization"
namespace UE::Virtualization
{
UE_REGISTER_VIRTUALIZATION_SYSTEM(UE::Virtualization::FVirtualizationManager, Default);
ENUM_CLASS_FLAGS(FVirtualizationManager::ECachingPolicy);
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
// Can be defined as 1 by programs target.cs files force the backend connections
// to lazy initialize on first use rather than when the system is initialized.
#ifndef UE_VIRTUALIZATION_CONNECTION_LAZY_INIT
#define UE_VIRTUALIZATION_CONNECTION_LAZY_INIT 0
#endif //UE_VIRTUALIZATION_CONNECTION_LAZY_INIT
#define UE_INLINE_ALLOCATION_COUNT 4
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
// TODO: Move to RegisterConsoleCommands
static TAutoConsoleVariable<bool> CVarLazyInitConnections(
TEXT("VA.LazyInitConnections"),
false,
TEXT("When true the VA backends will defer creating their connections until first use"));
//
#define UE_USE_GLOBAL_CVAR 1
#if UE_USE_GLOBAL_CVAR
static FAutoConsoleVariable CVarAllowPkgVirtualization(
TEXT("VA.AllowPkgVirtualization"),
true,
TEXT("When true submitting packages in the editor will no longer trigger the virtualization process")
);
#endif // UE_USE_GLOBAL_CVAR
/** Utility struct, similar to FScopeLock but allows the lock to be enabled/disabled more easily */
struct FConditionalScopeLock
{
UE_NONCOPYABLE(FConditionalScopeLock);
FConditionalScopeLock(FCriticalSection* InSyncObject, bool bShouldLock)
{
checkf(InSyncObject != nullptr, TEXT("InSyncObject must point to a valid FCriticalSection"));
if (bShouldLock)
{
SyncObject = InSyncObject;
SyncObject->Lock();
}
else
{
SyncObject = nullptr;
}
}
/** Destructor that performs a release on the synchronization object. */
~FConditionalScopeLock()
{
if (SyncObject != nullptr)
{
SyncObject->Unlock();
}
}
private:
FCriticalSection* SyncObject;
};
/**
* Utility class to help manage pull requests. When created it will remove invalid and duplicate requests so
* that backends do not need to worry about them.
* It will also prune the list of requests after each backend pull so that we only make requests for payloads
* that have not yet been found and on request provide a list of payloads that should be cached.
* On destruction it will then write the results back to the original requests. Duplicate requests will share
* references to the same payload in memory. Once destroyed all of the original requests should have a success
* or error status and none should be listed as pending.
*
* NOTE: This is intended to be used by FVirtualizationManager::PullDataFromAllBackends only, hence doing a
* few dangerous things like returning a TArrayView as we know it will not be misused. If this is ever taken
* into wider use we will have to revisit things like that.
*/
class FPullRequestCollection
{
public:
UE_NONCOPYABLE(FPullRequestCollection);
FPullRequestCollection() = delete;
FPullRequestCollection(TArrayView<FPullRequest> InRequests)
: OriginalRequests(InRequests)
{
CurrentRequests.Reserve(OriginalRequests.Num());
// Record each payload hash as we add it to CurrentRequests so that we only request duplicates once.
TSet<FIoHash, DefaultKeyFuncs<FIoHash>, TInlineSetAllocator<UE_INLINE_ALLOCATION_COUNT>> UniquePayloads;
for (FPullRequest& Request : OriginalRequests)
{
if (Request.GetIdentifier().IsZero())
{
Request.SetError();
UE_LOG(LogVirtualization, Error, TEXT("Attempting to pull a virtualized payload with an invalid FIoHash"));
}
else if (!UniquePayloads.Contains(Request.GetIdentifier()))
{
CurrentRequests.Add(Request);
UniquePayloads.Add(Request.GetIdentifier());
}
}
}
~FPullRequestCollection()
{
for (FPullRequest& Request : OriginalRequests)
{
if (FCompressedBuffer* Payload = LoadedPayloads.Find(Request.GetIdentifier()))
{
Request.SetPayload(*Payload);
}
else
{
Request.SetError();
}
}
}
/**
* Called after the requests from ::GetRequests have been pulled from a backend. Payloads that were
* successfully pulled will be removed from the request list and added to the LoadedPayloads map
* so that they can be assigned to the original requests later.
*
* @param Backend The backend that the payloads were pulled from
* @param bRequirePayloadsToCache Do we need a list of payloads that should be cached
*
* @return A list of requests that now need to be cached (if required)
*/
TArray<FPushRequest> OnPullCompleted(const IVirtualizationBackend& Backend, bool bRequirePayloadsToCache)
{
TArray<FPushRequest> PayloadsToCache;
if (bRequirePayloadsToCache)
{
PayloadsToCache.Reserve(CurrentRequests.Num());
}
for (int32 Index = 0; Index < CurrentRequests.Num();)
{
const FPullRequest& Request = CurrentRequests[Index];
if (Request.IsSuccess())
{
if (bRequirePayloadsToCache)
{
PayloadsToCache.Emplace(FPushRequest(Request.GetIdentifier(), Request.GetPayload(), FString()));
}
LoadedPayloads.Add(Request.GetIdentifier(), Request.GetPayload());
CurrentRequests.RemoveAtSwap(Index);
UE_LOG(LogVirtualization, VeryVerbose, TEXT("[%s] pulled payload '%s'"), *Backend.GetDebugName(), *LexToString(Request.GetIdentifier()));
}
else
{
++Index;
}
}
return PayloadsToCache;
}
/** Return the current list of requests that need to be made */
TArrayView<FPullRequest> GetRequests()
{
return CurrentRequests;
}
/** Returns if there are still requests that need servicing or not */
bool IsWorkComplete() const
{
return CurrentRequests.IsEmpty();
}
private:
TArrayView<FPullRequest> OriginalRequests;
TMap<FIoHash, FCompressedBuffer, TInlineSetAllocator<UE_INLINE_ALLOCATION_COUNT>> LoadedPayloads;
TArray<FPullRequest, TInlineAllocator<UE_INLINE_ALLOCATION_COUNT>> CurrentRequests;
};
const TCHAR* LexToString(EPackageFilterMode Value)
{
switch (Value)
{
case EPackageFilterMode::OptIn:
return TEXT("OptIn");
case EPackageFilterMode::OptOut:
return TEXT("OptOut");
default:
checkNoEntry();
return TEXT("");
}
}
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
bool LexTryParseString(EPackageFilterMode& OutValue, FStringView Buffer)
{
if (Buffer == TEXT("OptOut"))
{
OutValue = EPackageFilterMode::OptOut;
return true;
}
else if (Buffer == TEXT("OptIn"))
{
OutValue = EPackageFilterMode::OptIn;
return true;
}
return false;
}
/**
* Utility to check if a cmdline switch is present in the commandline under either of two names.
* Useful when transitioning from one command line to another.
*/
static bool IsCmdLineParamSet(const TCHAR* Cmd, const TCHAR* AlternativeCmd)
{
const TCHAR* CmdLine = FCommandLine::Get();
if (FParse::Param(CmdLine, Cmd))
{
return true;
}
if (FParse::Param(CmdLine, AlternativeCmd))
{
return true;
}
return false;
}
/**
* Utility to check if a cmdline value is present in the commandline under either of two names.
* Useful when transitioning from one command line to another.
*/
template<typename T>
static bool IsCmdLineValueSet(const TCHAR* Cmd, const TCHAR* AlternativeCmd, T& OutValue)
{
const TCHAR* CmdLine = FCommandLine::Get();
if (FParse::Value(CmdLine, Cmd, OutValue))
{
return true;
}
if (FParse::Value(CmdLine, AlternativeCmd, OutValue))
{
return true;
}
return false;
}
Virtualizing an asset will no longer display an error message if the project has no caching storage backends set up. #rb Per.Larsson #jira UE-171492 #rnx #preflight 6391f02d67018b14b581c0b0 - It is possible that a project might want to have persistent storage enabled but no caching storage, it is probably a bad idea but it should work. However before this fix doing so would cause an error to be logged during the virtualization of a package and fail the process. - During the virtualization process we now check if pushing is enabled for cache storage before trying to push there, if not then we log that the phase is being skipped. - Even though the above fixes the problem we would still get odd results when pushing payloads to cached storage without any backends enabled. -- We now check if the pushing process is disabled before processing requests, so we can fail faster. There is now also a proper error value for this that can be stored in each request (FPushRequest) where as previously they'd all still display "pending" -- We also check to see if the requested push type has any associated backend before processing requests and have a specific error value for this. Note that we consider - We also now force the visibility of the slow task progress bar, as otherwise we might not end up displaying the virtualization progress to the progress dialog (this is a work around to a long standing problem with the slow task system due to the time limit associated with updating the dialog via EnterProgressFrame, this needs to be fixed elsewhere) #ushell-cherrypick of 23445439 by paul.chipchase [CL 23461405 by paul chipchase in ue5-main branch]
2022-12-09 03:39:20 -05:00
/** Utility to set the same FPushResult on many requests at once */
static void SetPushRequestsResult(TArrayView<FPushRequest> Requests, FPushResult Result)
{
for (FPushRequest& Request : Requests)
{
Request.SetResult(Result);
}
}
/* Utility function for building up a lookup table of all available IBackendFactory interfaces*/
FVirtualizationManager::FRegistedFactories FindBackendFactories()
{
FVirtualizationManager::FRegistedFactories BackendFactories;
TArray<IVirtualizationBackendFactory*> FactoriesArray = IModularFeatures::Get().GetModularFeatureImplementations<IVirtualizationBackendFactory>(FName("VirtualizationBackendFactory"));
for (IVirtualizationBackendFactory* FactoryInterface : FactoriesArray)
{
checkf(FactoryInterface != nullptr, TEXT("A nullptr was added to the modular features for 'VirtualizationBackendFactory'"));
const FName FactoryName = FactoryInterface->GetName();
if (!BackendFactories.Contains(FactoryName))
{
BackendFactories.Add(FactoryName, FactoryInterface);
}
else
{
UE_LOG(LogVirtualization, Error, TEXT("Duplicate IBackendFactory found! Name '%s'"), *FactoryName.ToString());
}
}
return BackendFactories;
}
/* Utility function for finding entries in a given string*/
TArray<FString> ParseEntries(const FString& Data)
{
TArray<FString> Entries;
const TCHAR* DataPtr = *Data;
const TCHAR* EntryLabel = TEXT("Entry=");
const int32 EntryLabelLength = FCString::Strlen(EntryLabel);
FString ConfigEntryName;
while (FParse::Value(DataPtr, EntryLabel, ConfigEntryName))
{
Entries.Add(ConfigEntryName);
// Skip head so we can look for any additional entries (note that we might not skip past the existing
// entry has we have no idea how much whitespace was ignored by FParse, but it will be enough)
DataPtr += EntryLabelLength + ConfigEntryName.Len();
}
return Entries;
}
/**
* FPackagePath has strict requirements on how file paths are formated in order for it to be
* able to accept them. In theory the paths that the virtualization system are given are
* already in a good shape but as we do not know where they come from we cannot trust them.
* This utility will iterate over a list of untrusted filepaths and call various FPaths methods
* on them to make sure that they are all correct.
*/
TArray<FString> SanitizeFilePaths(TConstArrayView<FString> FilePaths)
{
TRACE_CPUPROFILER_EVENT_SCOPE(SanitizeFilePaths);
TArray<FString> SanitizedPaths;
SanitizedPaths.Reserve(FilePaths.Num());
for (const FString& Path : FilePaths)
{
FString SanitizedPath = Path;
FPaths::NormalizeFilename(SanitizedPath);
FPaths::RemoveDuplicateSlashes(SanitizedPath);
SanitizedPaths.Emplace(MoveTemp(SanitizedPath));
}
return SanitizedPaths;
}
/**
* Utility to make 'StorageType == EStorageType::Cache' checks easier while EStorageType::Local continues to exist.
* When the deprecated value is removed this can also be removed and code calling it can just check for EStorageType::Cache */
bool IsCacheType(EStorageType StorageType)
{
PRAGMA_DISABLE_DEPRECATION_WARNINGS
return StorageType == EStorageType::Local || StorageType == EStorageType::Cache;
PRAGMA_ENABLE_DEPRECATION_WARNINGS
}
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
/**
* Profiling data allowing us to track how payloads are being push/pulled during the lifespan of the process. Note that as all backends are
* created at the same time, we don't need to add locked when accessing the maps. In addition FCookStats is thread safe when adding hits/misses
* so we don't have to worry about that either.
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
* We keep the FCookStats here rather than as a member of IVirtualizationBackend to try and avoid the backends needing to be aware of the data that
* we are gathering at all. This way all profiling code is kept to this cpp.
*/
namespace Profiling
{
#if ENABLE_COOK_STATS
TMap<FString, FCookStats::CallStats> CacheStats;
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
TMap<FString, FCookStats::CallStats> PushStats;
TMap<FString, FCookStats::CallStats> PullStats;
void CreateStats(const IVirtualizationBackend& Backend)
{
CacheStats.Add(Backend.GetDebugName());
PushStats.Add(Backend.GetDebugName());
PullStats.Add(Backend.GetDebugName());
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
}
FCookStats::CallStats& GetCacheStats(const IVirtualizationBackend& Backend)
{
return *CacheStats.Find(Backend.GetDebugName());
}
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
FCookStats::CallStats& GetPushStats(const IVirtualizationBackend& Backend)
{
return *PushStats.Find(Backend.GetDebugName());
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
}
FCookStats::CallStats& GetPullStats(const IVirtualizationBackend& Backend)
{
return *PullStats.Find(Backend.GetDebugName());
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
}
bool HasProfilingData(const TMap<FString, FCookStats::CallStats>& Stats)
{
for (const auto& Iterator : Stats)
{
if (Iterator.Value.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Counter) > 0)
{
return true;
}
if (Iterator.Value.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Miss, FCookStats::CallStats::EStatType::Counter) > 0)
{
return true;
}
}
return false;
}
/** Returns true if we have gathered any profiling data at all */
bool HasProfilingData()
{
return HasProfilingData(CacheStats) || HasProfilingData(PushStats) || HasProfilingData(PullStats);
}
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
void LogStats()
{
UE_LOG(LogVirtualization, Display, TEXT(""));
UE_LOG(LogVirtualization, Display, TEXT("Virtualization ProfileData"));
UE_LOG(LogVirtualization, Display, TEXT("=================================================================================================="));
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
if (!HasProfilingData())
{
UE_LOG(LogVirtualization, Display, TEXT("Skipping profile data as there was no activity to report"));
return; // Early out if we have no data
}
auto PrintStats = [](const TCHAR* Name, const TMap<FString, FCookStats::CallStats>& Stats)
{
if (HasProfilingData(Stats))
{
UE_LOG(LogVirtualization, Display, TEXT("%-40s|%10s|%17s|%12s|%14s|"), Name, TEXT("TotalCount"), TEXT("TotalSize (MB)"), TEXT("TotalTime(s)"), TEXT("DataRate(MB/S)"));
UE_LOG(LogVirtualization, Display, TEXT("----------------------------------------|----------|-----------------|------------|--------------|"));
for (const auto& Iterator : Stats)
{
const int64 Count = Iterator.Value.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Counter);
const double Time = Iterator.Value.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Cycles) * FPlatformTime::GetSecondsPerCycle();
const double DataSizeMB = Iterator.Value.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Bytes) / (1024.0f * 1024.0f);
const double MBps = Time != 0.0 ? (DataSizeMB / Time) : 0.0;
UE_LOG(LogVirtualization, Display, TEXT("%-40.40s|%10lld|%17.1f|%12.3f|%14.3f|"),
*Iterator.Key,
Count,
DataSizeMB,
Time,
MBps);
}
UE_LOG(LogVirtualization, Display, TEXT("=================================================================================================="));
}
};
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
PrintStats(TEXT("Caching Data"), CacheStats);
PrintStats(TEXT("Pushing Data"), PushStats);
PrintStats(TEXT("Pulling Data"), PullStats);
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
}
#endif // ENABLE_COOK_STATS
} //namespace Profiling
FVirtualizationManager::FVirtualizationManager()
: bAllowPackageVirtualization(true)
, CachingPolicy(ECachingPolicy::AlwaysCache)
, MinPayloadLength(0)
, BackendGraphName(TEXT("ContentVirtualizationBackendGraph_None"))
, VirtualizationProcessTag(TEXT("#virtualized"))
, FilteringMode(EPackageFilterMode::OptOut)
Add a config file option to allow payloads stored in .umap and associated "_builddata.uasset" files to be filtered from the virtualization process. This option defaults to true. #rb Per.Larsson #jira UE-156750 #rnx #preflight 62f212e13b773d04161ee7dd ### Problem - The payloads stored in map files tend to change more than other assets and would cause a lot more churn in the VA system. - Some other systems like the landscape component are not able to sensibly continue if their payloads cannot be accessed (heightmaps for exmaple) and would prefer not to allow virtualization. - As a short term fix we need an option to disable the virtualization on all payloads in map files. Future improvements to the filtering system will allow systems to more easily opt their payloads out of virtualization. When this is functional we might want to change the default from true to false. ### Feature - The config optionf for this filtering is "[Core.VirtualizationModule]FilterMapContent=True" - Testing if the owning UObject for a payload is in a umap can get tricky, because we not only need to check the umap but we also need to check if it is in a "_builddata.uasset" file, which is an additional file we store next to a umap containing things like lightmaps etc. - At the moment we check for this by finding the outermost object for the given owner and check to see if it is a ULevel, UWorld or UMapBuildDataRegistry. This is a bit of a kludge but the types we need to check against are not accessible by this module and making them accessible will pull in a lot of dependencies that we'd prefer not to add. -- One improvement might be to tag the FLinkerSave with the info we need and passing that into the serialization process rather than trying to work it out ourselves but I am wary of making that change until we are 100% sure that we want to keep this feature. ### Refactor - Removed IVirtualizationSystem::IsDisabledForObject and replaced it with ::FilterPayload which can return multiple reasons for preventing a payload from virtualizing. (the method was added during 5.1 development so it should be fine to just replace it without deprecation) -- The original behaviour for FVirtualizationManager::IsDisabledForObject has been moved to FVirtualizationManager::ShouldVirtualizeAsset - Added a new header to declare enums/types used by the various parts of the virtualization system and started by moving EPayloadFilterReason there from the package trailer header. This allows both the core API and PackageTrailer to use EPayloadFilterReason without creating overburdened header dependencies. -- EPayloadFilterReason has moved from the UE namespace to UE::Virtualization so the package trailer code needed updating accordingly. - EditorBulkData will ask the virtualization system for the base filter reason, then add it's own reasons if UE_ENABLE_VIRTUALIZATION_TOGGLE is enabled. This bit of code will be removed for 5.1 [CL 21283179 by paul chipchase in ue5-main branch]
2022-08-09 07:51:55 -04:00
, bFilterMapContent(true)
Add an ini file option which when set to true allows package submissions to source control to go ahead even if the virtualization process failed. #rb none #jira UE-159596 #rnx #preflight 62d94160110da0f944afdd32 ### Problem - When rolling our virtualization to projects we have run into a number of set up problems which has caused users to fail to submit packages from the editor as when the virtualization failed we prevented the overall submit from going through. - Although we will eventually work through all of these problems and add better fault tolerance for now it is annoying for the content team so we need an easy way for a project to allow package submits to be completed even if the virtualization process part of the submit failed. - Worth noting that the virtualization process failing should never affect the state of the package files, the only downside is that the packages may not be virtualized. ### Fix - The virtualization/rehydration of packages now return an enum instead of a bool although at the moment we are only returning Success and Failed, but it will allow us to expand in the future - Combined the code calling the virtualization process from both the source control window and the source control changelist window into a single utility function. -- Now the two windows only diverge on how they report failure to the user. - This new utility function now checks to see if the virtualization manager suggests if failing the virtualization process should block any package submission to source control or not. - I am not happy with this solution, but I haven't come up with anything that feels right, this solution will at least work. [CL 21199597 by paul chipchase in ue5-main branch]
2022-07-21 08:31:47 -04:00
, bAllowSubmitIfVirtualizationFailed(false)
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
, bLazyInitConnections(false)
, bUseLegacyErrorHandling(true)
, bForceCachingOnPull(false)
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
, bPendingBackendConnections(false)
{
}
FVirtualizationManager::~FVirtualizationManager()
{
for (const TPair<IConsoleVariable*, FDelegateHandle>& KV : DebugValues.ConsoleDelegateHandles)
{
IConsoleVariable* ConsoleVariable = KV.Key;
const FDelegateHandle& Handle = KV.Value;
ConsoleVariable->OnChangedDelegate().Remove(Handle);
}
for (IConsoleObject* ConsoleObject : DebugValues.ConsoleObjects)
{
IConsoleManager::Get().UnregisterConsoleObject(ConsoleObject);
}
UE_LOG(LogVirtualization, Log, TEXT("Destroying backends"));
CacheStorageBackends.Empty();
PersistentStorageBackends.Empty();
PullEnabledBackends.Empty();
AllBackends.Empty(); // This will delete all backends and beyond this point all references to them are invalid
UE_LOG(LogVirtualization, Log, TEXT("Virtualization manager destroyed"));
}
bool FVirtualizationManager::Initialize(const FInitParams& InitParams)
{
TRACE_CPUPROFILER_EVENT_SCOPE(FVirtualizationManager::Initialize);
UE_LOG(LogVirtualization, Display, TEXT("Initializing the virtualization manager..."));
// TODO: Ideally we'd break this down further, or at least have a FScopedSlowTask for each
// backend initialization but the slow task system will only update the UI every 0.2 seconds
// so if we have too many small tasks we might show misleading data to the user, so it is
// better for us to have a single scope here at the top level and rely on UnrealInsights for
// detailed profiling unless we do something to how FScopedSlowTask updates the UI.
FScopedSlowTask SlowTask(1.0f, LOCTEXT("VAInitialize", "Initializing virtualized asset system..."));
SlowTask.EnterProgressFrame(1.0f);
ProjectName = InitParams.ProjectName;
ApplySettingsFromConfigFiles(InitParams.ConfigFile);
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
ApplySettingsFromFromCmdline();
ApplySettingsFromCVar();
ApplyDebugSettingsFromFromCmdline();
// Do this after all of the command line settings have been processed and any
// requested debug value changes already set.
RegisterConsoleCommands();
MountBackends(InitParams.ConfigFile);
UE_LOG(LogVirtualization, Display, TEXT("Virtualization manager initialization completed"));
return true;
}
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
bool FVirtualizationManager::IsEnabled() const
{
return !AllBackends.IsEmpty();
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
}
bool FVirtualizationManager::IsPushingEnabled(EStorageType StorageType) const
{
if (!bAllowPackageVirtualization)
{
return false;
}
switch (StorageType)
{
PRAGMA_DISABLE_DEPRECATION_WARNINGS
case EStorageType::Local:
PRAGMA_ENABLE_DEPRECATION_WARNINGS
case EStorageType::Cache:
return !CacheStorageBackends.IsEmpty() && EnumHasAllFlags(CachingPolicy, ECachingPolicy::CacheOnPush);
break;
case EStorageType::Persistent:
return !PersistentStorageBackends.IsEmpty();
break;
default:
checkNoEntry();
return false;
break;
}
}
Add a config file option to allow payloads stored in .umap and associated "_builddata.uasset" files to be filtered from the virtualization process. This option defaults to true. #rb Per.Larsson #jira UE-156750 #rnx #preflight 62f212e13b773d04161ee7dd ### Problem - The payloads stored in map files tend to change more than other assets and would cause a lot more churn in the VA system. - Some other systems like the landscape component are not able to sensibly continue if their payloads cannot be accessed (heightmaps for exmaple) and would prefer not to allow virtualization. - As a short term fix we need an option to disable the virtualization on all payloads in map files. Future improvements to the filtering system will allow systems to more easily opt their payloads out of virtualization. When this is functional we might want to change the default from true to false. ### Feature - The config optionf for this filtering is "[Core.VirtualizationModule]FilterMapContent=True" - Testing if the owning UObject for a payload is in a umap can get tricky, because we not only need to check the umap but we also need to check if it is in a "_builddata.uasset" file, which is an additional file we store next to a umap containing things like lightmaps etc. - At the moment we check for this by finding the outermost object for the given owner and check to see if it is a ULevel, UWorld or UMapBuildDataRegistry. This is a bit of a kludge but the types we need to check against are not accessible by this module and making them accessible will pull in a lot of dependencies that we'd prefer not to add. -- One improvement might be to tag the FLinkerSave with the info we need and passing that into the serialization process rather than trying to work it out ourselves but I am wary of making that change until we are 100% sure that we want to keep this feature. ### Refactor - Removed IVirtualizationSystem::IsDisabledForObject and replaced it with ::FilterPayload which can return multiple reasons for preventing a payload from virtualizing. (the method was added during 5.1 development so it should be fine to just replace it without deprecation) -- The original behaviour for FVirtualizationManager::IsDisabledForObject has been moved to FVirtualizationManager::ShouldVirtualizeAsset - Added a new header to declare enums/types used by the various parts of the virtualization system and started by moving EPayloadFilterReason there from the package trailer header. This allows both the core API and PackageTrailer to use EPayloadFilterReason without creating overburdened header dependencies. -- EPayloadFilterReason has moved from the UE namespace to UE::Virtualization so the package trailer code needed updating accordingly. - EditorBulkData will ask the virtualization system for the base filter reason, then add it's own reasons if UE_ENABLE_VIRTUALIZATION_TOGGLE is enabled. This bit of code will be removed for 5.1 [CL 21283179 by paul chipchase in ue5-main branch]
2022-08-09 07:51:55 -04:00
EPayloadFilterReason FVirtualizationManager::FilterPayload(const UObject* Owner) const
It is now possible to disable virtualization for all payloads owned by a specific asset type by adding the name of the asset to [Core.ContentVirtualization]DisabledAsset string array in the engine ini file. #rb Per.Larsson #rnx #jira UE-151377 #preflight 628364050039ea57a52d6989 ### Virtualization - [Core.ContentVirtualization] in the engine ini file now supports an array called 'DisabledAsset' which can be used to name asset types that should not virtualize their payloads. -- By default (in BaseEngine.ini) we have disabled the StaticMesh asset as we know it will crash if a payload is missing and the SoundWave asset as it still is pending testing. - This new way to disable virtualization is data driven. The older hard coded method has not been removed but will likely be reworked in a future submit. - Now when an editor bulkdata is adding it's payload to the package trailer builder during package save it will poll the virtualization system with a call to the new method ::IsDisabledForObject by passing in it's owner. -- If the owner is valid and was present in the 'DisabledAsset' array then the method will return true and the EPayloadFlags::DisableVirtualization flag will be applied. ### Package Trailer - The pre-existing functionality of enum EPayloadFilter has been moved to a new enum EPayloadStorageType as will only filter payloads based on their storage type. - EPayloadFilter has been modified to filter payloads based on functionality although at the moment the only thing it can filter for is to return payloads that can be virtualized, it is left for future expansion. - EPayloadFlags has been reduced to a uint16 with the remaining 2bytes being turned into a new member EPayloadFilterReason. - This new member allows us to record the exact reason why a payload is excluded from virtualization. If it is zero then the payload can virtualize, otherwise it will contain one or more reasons as to why it is being excluded. For this reason the enum is a bitfield. - Added overloads of ::GetPayloads and ::GetNumPayloads that take EPayloadFilter rather than a EPayloadStorageType - Added wrappers around all AccessMode types for FLookupTableEntry. - FPackageTrailerBuilder has been extended to take a EPayloadFilterReason so that the caller can already provide a reason why the payload cannot be virtualized. -- As a future peace of work this will probably be changed and we will ask the caller to pass in the owner UObject pointer instead and then we will process the filtering when building the package trailer to a) keep all of the filtering code in one place b) keep the filtering consistent ### PackageSubmissionChecks - The virtualization process in will now request the payloads that can be virtualized from the package trailer, which respects the new payload flag, rather than requesting all locally stored payloads. ### UObjects - There is no need for the SoundWave or MeshDescription classes to opt out of virtualization on construction. This will be done when the package is saved and is now data driven rather than being hardcoded. ### DumpPackagePayloadInfo - The command has been updated to also display the filter reasons applied to each payload [CL 20240971 by paul chipchase in ue5-main branch]
2022-05-17 07:54:28 -04:00
{
Add a config file option to allow payloads stored in .umap and associated "_builddata.uasset" files to be filtered from the virtualization process. This option defaults to true. #rb Per.Larsson #jira UE-156750 #rnx #preflight 62f212e13b773d04161ee7dd ### Problem - The payloads stored in map files tend to change more than other assets and would cause a lot more churn in the VA system. - Some other systems like the landscape component are not able to sensibly continue if their payloads cannot be accessed (heightmaps for exmaple) and would prefer not to allow virtualization. - As a short term fix we need an option to disable the virtualization on all payloads in map files. Future improvements to the filtering system will allow systems to more easily opt their payloads out of virtualization. When this is functional we might want to change the default from true to false. ### Feature - The config optionf for this filtering is "[Core.VirtualizationModule]FilterMapContent=True" - Testing if the owning UObject for a payload is in a umap can get tricky, because we not only need to check the umap but we also need to check if it is in a "_builddata.uasset" file, which is an additional file we store next to a umap containing things like lightmaps etc. - At the moment we check for this by finding the outermost object for the given owner and check to see if it is a ULevel, UWorld or UMapBuildDataRegistry. This is a bit of a kludge but the types we need to check against are not accessible by this module and making them accessible will pull in a lot of dependencies that we'd prefer not to add. -- One improvement might be to tag the FLinkerSave with the info we need and passing that into the serialization process rather than trying to work it out ourselves but I am wary of making that change until we are 100% sure that we want to keep this feature. ### Refactor - Removed IVirtualizationSystem::IsDisabledForObject and replaced it with ::FilterPayload which can return multiple reasons for preventing a payload from virtualizing. (the method was added during 5.1 development so it should be fine to just replace it without deprecation) -- The original behaviour for FVirtualizationManager::IsDisabledForObject has been moved to FVirtualizationManager::ShouldVirtualizeAsset - Added a new header to declare enums/types used by the various parts of the virtualization system and started by moving EPayloadFilterReason there from the package trailer header. This allows both the core API and PackageTrailer to use EPayloadFilterReason without creating overburdened header dependencies. -- EPayloadFilterReason has moved from the UE namespace to UE::Virtualization so the package trailer code needed updating accordingly. - EditorBulkData will ask the virtualization system for the base filter reason, then add it's own reasons if UE_ENABLE_VIRTUALIZATION_TOGGLE is enabled. This bit of code will be removed for 5.1 [CL 21283179 by paul chipchase in ue5-main branch]
2022-08-09 07:51:55 -04:00
UE::Virtualization::EPayloadFilterReason PayloadFilter = UE::Virtualization::EPayloadFilterReason::None;
if (!ShouldVirtualizeAsset(Owner))
It is now possible to disable virtualization for all payloads owned by a specific asset type by adding the name of the asset to [Core.ContentVirtualization]DisabledAsset string array in the engine ini file. #rb Per.Larsson #rnx #jira UE-151377 #preflight 628364050039ea57a52d6989 ### Virtualization - [Core.ContentVirtualization] in the engine ini file now supports an array called 'DisabledAsset' which can be used to name asset types that should not virtualize their payloads. -- By default (in BaseEngine.ini) we have disabled the StaticMesh asset as we know it will crash if a payload is missing and the SoundWave asset as it still is pending testing. - This new way to disable virtualization is data driven. The older hard coded method has not been removed but will likely be reworked in a future submit. - Now when an editor bulkdata is adding it's payload to the package trailer builder during package save it will poll the virtualization system with a call to the new method ::IsDisabledForObject by passing in it's owner. -- If the owner is valid and was present in the 'DisabledAsset' array then the method will return true and the EPayloadFlags::DisableVirtualization flag will be applied. ### Package Trailer - The pre-existing functionality of enum EPayloadFilter has been moved to a new enum EPayloadStorageType as will only filter payloads based on their storage type. - EPayloadFilter has been modified to filter payloads based on functionality although at the moment the only thing it can filter for is to return payloads that can be virtualized, it is left for future expansion. - EPayloadFlags has been reduced to a uint16 with the remaining 2bytes being turned into a new member EPayloadFilterReason. - This new member allows us to record the exact reason why a payload is excluded from virtualization. If it is zero then the payload can virtualize, otherwise it will contain one or more reasons as to why it is being excluded. For this reason the enum is a bitfield. - Added overloads of ::GetPayloads and ::GetNumPayloads that take EPayloadFilter rather than a EPayloadStorageType - Added wrappers around all AccessMode types for FLookupTableEntry. - FPackageTrailerBuilder has been extended to take a EPayloadFilterReason so that the caller can already provide a reason why the payload cannot be virtualized. -- As a future peace of work this will probably be changed and we will ask the caller to pass in the owner UObject pointer instead and then we will process the filtering when building the package trailer to a) keep all of the filtering code in one place b) keep the filtering consistent ### PackageSubmissionChecks - The virtualization process in will now request the payloads that can be virtualized from the package trailer, which respects the new payload flag, rather than requesting all locally stored payloads. ### UObjects - There is no need for the SoundWave or MeshDescription classes to opt out of virtualization on construction. This will be done when the package is saved and is now data driven rather than being hardcoded. ### DumpPackagePayloadInfo - The command has been updated to also display the filter reasons applied to each payload [CL 20240971 by paul chipchase in ue5-main branch]
2022-05-17 07:54:28 -04:00
{
Add a config file option to allow payloads stored in .umap and associated "_builddata.uasset" files to be filtered from the virtualization process. This option defaults to true. #rb Per.Larsson #jira UE-156750 #rnx #preflight 62f212e13b773d04161ee7dd ### Problem - The payloads stored in map files tend to change more than other assets and would cause a lot more churn in the VA system. - Some other systems like the landscape component are not able to sensibly continue if their payloads cannot be accessed (heightmaps for exmaple) and would prefer not to allow virtualization. - As a short term fix we need an option to disable the virtualization on all payloads in map files. Future improvements to the filtering system will allow systems to more easily opt their payloads out of virtualization. When this is functional we might want to change the default from true to false. ### Feature - The config optionf for this filtering is "[Core.VirtualizationModule]FilterMapContent=True" - Testing if the owning UObject for a payload is in a umap can get tricky, because we not only need to check the umap but we also need to check if it is in a "_builddata.uasset" file, which is an additional file we store next to a umap containing things like lightmaps etc. - At the moment we check for this by finding the outermost object for the given owner and check to see if it is a ULevel, UWorld or UMapBuildDataRegistry. This is a bit of a kludge but the types we need to check against are not accessible by this module and making them accessible will pull in a lot of dependencies that we'd prefer not to add. -- One improvement might be to tag the FLinkerSave with the info we need and passing that into the serialization process rather than trying to work it out ourselves but I am wary of making that change until we are 100% sure that we want to keep this feature. ### Refactor - Removed IVirtualizationSystem::IsDisabledForObject and replaced it with ::FilterPayload which can return multiple reasons for preventing a payload from virtualizing. (the method was added during 5.1 development so it should be fine to just replace it without deprecation) -- The original behaviour for FVirtualizationManager::IsDisabledForObject has been moved to FVirtualizationManager::ShouldVirtualizeAsset - Added a new header to declare enums/types used by the various parts of the virtualization system and started by moving EPayloadFilterReason there from the package trailer header. This allows both the core API and PackageTrailer to use EPayloadFilterReason without creating overburdened header dependencies. -- EPayloadFilterReason has moved from the UE namespace to UE::Virtualization so the package trailer code needed updating accordingly. - EditorBulkData will ask the virtualization system for the base filter reason, then add it's own reasons if UE_ENABLE_VIRTUALIZATION_TOGGLE is enabled. This bit of code will be removed for 5.1 [CL 21283179 by paul chipchase in ue5-main branch]
2022-08-09 07:51:55 -04:00
PayloadFilter |= UE::Virtualization::EPayloadFilterReason::Asset;
It is now possible to disable virtualization for all payloads owned by a specific asset type by adding the name of the asset to [Core.ContentVirtualization]DisabledAsset string array in the engine ini file. #rb Per.Larsson #rnx #jira UE-151377 #preflight 628364050039ea57a52d6989 ### Virtualization - [Core.ContentVirtualization] in the engine ini file now supports an array called 'DisabledAsset' which can be used to name asset types that should not virtualize their payloads. -- By default (in BaseEngine.ini) we have disabled the StaticMesh asset as we know it will crash if a payload is missing and the SoundWave asset as it still is pending testing. - This new way to disable virtualization is data driven. The older hard coded method has not been removed but will likely be reworked in a future submit. - Now when an editor bulkdata is adding it's payload to the package trailer builder during package save it will poll the virtualization system with a call to the new method ::IsDisabledForObject by passing in it's owner. -- If the owner is valid and was present in the 'DisabledAsset' array then the method will return true and the EPayloadFlags::DisableVirtualization flag will be applied. ### Package Trailer - The pre-existing functionality of enum EPayloadFilter has been moved to a new enum EPayloadStorageType as will only filter payloads based on their storage type. - EPayloadFilter has been modified to filter payloads based on functionality although at the moment the only thing it can filter for is to return payloads that can be virtualized, it is left for future expansion. - EPayloadFlags has been reduced to a uint16 with the remaining 2bytes being turned into a new member EPayloadFilterReason. - This new member allows us to record the exact reason why a payload is excluded from virtualization. If it is zero then the payload can virtualize, otherwise it will contain one or more reasons as to why it is being excluded. For this reason the enum is a bitfield. - Added overloads of ::GetPayloads and ::GetNumPayloads that take EPayloadFilter rather than a EPayloadStorageType - Added wrappers around all AccessMode types for FLookupTableEntry. - FPackageTrailerBuilder has been extended to take a EPayloadFilterReason so that the caller can already provide a reason why the payload cannot be virtualized. -- As a future peace of work this will probably be changed and we will ask the caller to pass in the owner UObject pointer instead and then we will process the filtering when building the package trailer to a) keep all of the filtering code in one place b) keep the filtering consistent ### PackageSubmissionChecks - The virtualization process in will now request the payloads that can be virtualized from the package trailer, which respects the new payload flag, rather than requesting all locally stored payloads. ### UObjects - There is no need for the SoundWave or MeshDescription classes to opt out of virtualization on construction. This will be done when the package is saved and is now data driven rather than being hardcoded. ### DumpPackagePayloadInfo - The command has been updated to also display the filter reasons applied to each payload [CL 20240971 by paul chipchase in ue5-main branch]
2022-05-17 07:54:28 -04:00
}
Add a config file option to allow payloads stored in .umap and associated "_builddata.uasset" files to be filtered from the virtualization process. This option defaults to true. #rb Per.Larsson #jira UE-156750 #rnx #preflight 62f212e13b773d04161ee7dd ### Problem - The payloads stored in map files tend to change more than other assets and would cause a lot more churn in the VA system. - Some other systems like the landscape component are not able to sensibly continue if their payloads cannot be accessed (heightmaps for exmaple) and would prefer not to allow virtualization. - As a short term fix we need an option to disable the virtualization on all payloads in map files. Future improvements to the filtering system will allow systems to more easily opt their payloads out of virtualization. When this is functional we might want to change the default from true to false. ### Feature - The config optionf for this filtering is "[Core.VirtualizationModule]FilterMapContent=True" - Testing if the owning UObject for a payload is in a umap can get tricky, because we not only need to check the umap but we also need to check if it is in a "_builddata.uasset" file, which is an additional file we store next to a umap containing things like lightmaps etc. - At the moment we check for this by finding the outermost object for the given owner and check to see if it is a ULevel, UWorld or UMapBuildDataRegistry. This is a bit of a kludge but the types we need to check against are not accessible by this module and making them accessible will pull in a lot of dependencies that we'd prefer not to add. -- One improvement might be to tag the FLinkerSave with the info we need and passing that into the serialization process rather than trying to work it out ourselves but I am wary of making that change until we are 100% sure that we want to keep this feature. ### Refactor - Removed IVirtualizationSystem::IsDisabledForObject and replaced it with ::FilterPayload which can return multiple reasons for preventing a payload from virtualizing. (the method was added during 5.1 development so it should be fine to just replace it without deprecation) -- The original behaviour for FVirtualizationManager::IsDisabledForObject has been moved to FVirtualizationManager::ShouldVirtualizeAsset - Added a new header to declare enums/types used by the various parts of the virtualization system and started by moving EPayloadFilterReason there from the package trailer header. This allows both the core API and PackageTrailer to use EPayloadFilterReason without creating overburdened header dependencies. -- EPayloadFilterReason has moved from the UE namespace to UE::Virtualization so the package trailer code needed updating accordingly. - EditorBulkData will ask the virtualization system for the base filter reason, then add it's own reasons if UE_ENABLE_VIRTUALIZATION_TOGGLE is enabled. This bit of code will be removed for 5.1 [CL 21283179 by paul chipchase in ue5-main branch]
2022-08-09 07:51:55 -04:00
// TODO: If we keep this feature long term then we might want to work this out in SavePackage.cpp and pass the info
// via FLinkerSave rather than the following code.
if (bFilterMapContent)
It is now possible to disable virtualization for all payloads owned by a specific asset type by adding the name of the asset to [Core.ContentVirtualization]DisabledAsset string array in the engine ini file. #rb Per.Larsson #rnx #jira UE-151377 #preflight 628364050039ea57a52d6989 ### Virtualization - [Core.ContentVirtualization] in the engine ini file now supports an array called 'DisabledAsset' which can be used to name asset types that should not virtualize their payloads. -- By default (in BaseEngine.ini) we have disabled the StaticMesh asset as we know it will crash if a payload is missing and the SoundWave asset as it still is pending testing. - This new way to disable virtualization is data driven. The older hard coded method has not been removed but will likely be reworked in a future submit. - Now when an editor bulkdata is adding it's payload to the package trailer builder during package save it will poll the virtualization system with a call to the new method ::IsDisabledForObject by passing in it's owner. -- If the owner is valid and was present in the 'DisabledAsset' array then the method will return true and the EPayloadFlags::DisableVirtualization flag will be applied. ### Package Trailer - The pre-existing functionality of enum EPayloadFilter has been moved to a new enum EPayloadStorageType as will only filter payloads based on their storage type. - EPayloadFilter has been modified to filter payloads based on functionality although at the moment the only thing it can filter for is to return payloads that can be virtualized, it is left for future expansion. - EPayloadFlags has been reduced to a uint16 with the remaining 2bytes being turned into a new member EPayloadFilterReason. - This new member allows us to record the exact reason why a payload is excluded from virtualization. If it is zero then the payload can virtualize, otherwise it will contain one or more reasons as to why it is being excluded. For this reason the enum is a bitfield. - Added overloads of ::GetPayloads and ::GetNumPayloads that take EPayloadFilter rather than a EPayloadStorageType - Added wrappers around all AccessMode types for FLookupTableEntry. - FPackageTrailerBuilder has been extended to take a EPayloadFilterReason so that the caller can already provide a reason why the payload cannot be virtualized. -- As a future peace of work this will probably be changed and we will ask the caller to pass in the owner UObject pointer instead and then we will process the filtering when building the package trailer to a) keep all of the filtering code in one place b) keep the filtering consistent ### PackageSubmissionChecks - The virtualization process in will now request the payloads that can be virtualized from the package trailer, which respects the new payload flag, rather than requesting all locally stored payloads. ### UObjects - There is no need for the SoundWave or MeshDescription classes to opt out of virtualization on construction. This will be done when the package is saved and is now data driven rather than being hardcoded. ### DumpPackagePayloadInfo - The command has been updated to also display the filter reasons applied to each payload [CL 20240971 by paul chipchase in ue5-main branch]
2022-05-17 07:54:28 -04:00
{
Add a config file option to allow payloads stored in .umap and associated "_builddata.uasset" files to be filtered from the virtualization process. This option defaults to true. #rb Per.Larsson #jira UE-156750 #rnx #preflight 62f212e13b773d04161ee7dd ### Problem - The payloads stored in map files tend to change more than other assets and would cause a lot more churn in the VA system. - Some other systems like the landscape component are not able to sensibly continue if their payloads cannot be accessed (heightmaps for exmaple) and would prefer not to allow virtualization. - As a short term fix we need an option to disable the virtualization on all payloads in map files. Future improvements to the filtering system will allow systems to more easily opt their payloads out of virtualization. When this is functional we might want to change the default from true to false. ### Feature - The config optionf for this filtering is "[Core.VirtualizationModule]FilterMapContent=True" - Testing if the owning UObject for a payload is in a umap can get tricky, because we not only need to check the umap but we also need to check if it is in a "_builddata.uasset" file, which is an additional file we store next to a umap containing things like lightmaps etc. - At the moment we check for this by finding the outermost object for the given owner and check to see if it is a ULevel, UWorld or UMapBuildDataRegistry. This is a bit of a kludge but the types we need to check against are not accessible by this module and making them accessible will pull in a lot of dependencies that we'd prefer not to add. -- One improvement might be to tag the FLinkerSave with the info we need and passing that into the serialization process rather than trying to work it out ourselves but I am wary of making that change until we are 100% sure that we want to keep this feature. ### Refactor - Removed IVirtualizationSystem::IsDisabledForObject and replaced it with ::FilterPayload which can return multiple reasons for preventing a payload from virtualizing. (the method was added during 5.1 development so it should be fine to just replace it without deprecation) -- The original behaviour for FVirtualizationManager::IsDisabledForObject has been moved to FVirtualizationManager::ShouldVirtualizeAsset - Added a new header to declare enums/types used by the various parts of the virtualization system and started by moving EPayloadFilterReason there from the package trailer header. This allows both the core API and PackageTrailer to use EPayloadFilterReason without creating overburdened header dependencies. -- EPayloadFilterReason has moved from the UE namespace to UE::Virtualization so the package trailer code needed updating accordingly. - EditorBulkData will ask the virtualization system for the base filter reason, then add it's own reasons if UE_ENABLE_VIRTUALIZATION_TOGGLE is enabled. This bit of code will be removed for 5.1 [CL 21283179 by paul chipchase in ue5-main branch]
2022-08-09 07:51:55 -04:00
if (const UObject* Outer = Owner->GetOutermostObject())
{
if (const UClass* OuterClass = Outer->GetClass())
{
const FName OuterClassName = OuterClass->GetFName();
if (OuterClassName == FName("Level") ||
OuterClassName == FName("World") ||
OuterClassName == FName("MapBuildDataRegistry"))
{
PayloadFilter |= UE::Virtualization::EPayloadFilterReason::MapContent;
}
}
}
It is now possible to disable virtualization for all payloads owned by a specific asset type by adding the name of the asset to [Core.ContentVirtualization]DisabledAsset string array in the engine ini file. #rb Per.Larsson #rnx #jira UE-151377 #preflight 628364050039ea57a52d6989 ### Virtualization - [Core.ContentVirtualization] in the engine ini file now supports an array called 'DisabledAsset' which can be used to name asset types that should not virtualize their payloads. -- By default (in BaseEngine.ini) we have disabled the StaticMesh asset as we know it will crash if a payload is missing and the SoundWave asset as it still is pending testing. - This new way to disable virtualization is data driven. The older hard coded method has not been removed but will likely be reworked in a future submit. - Now when an editor bulkdata is adding it's payload to the package trailer builder during package save it will poll the virtualization system with a call to the new method ::IsDisabledForObject by passing in it's owner. -- If the owner is valid and was present in the 'DisabledAsset' array then the method will return true and the EPayloadFlags::DisableVirtualization flag will be applied. ### Package Trailer - The pre-existing functionality of enum EPayloadFilter has been moved to a new enum EPayloadStorageType as will only filter payloads based on their storage type. - EPayloadFilter has been modified to filter payloads based on functionality although at the moment the only thing it can filter for is to return payloads that can be virtualized, it is left for future expansion. - EPayloadFlags has been reduced to a uint16 with the remaining 2bytes being turned into a new member EPayloadFilterReason. - This new member allows us to record the exact reason why a payload is excluded from virtualization. If it is zero then the payload can virtualize, otherwise it will contain one or more reasons as to why it is being excluded. For this reason the enum is a bitfield. - Added overloads of ::GetPayloads and ::GetNumPayloads that take EPayloadFilter rather than a EPayloadStorageType - Added wrappers around all AccessMode types for FLookupTableEntry. - FPackageTrailerBuilder has been extended to take a EPayloadFilterReason so that the caller can already provide a reason why the payload cannot be virtualized. -- As a future peace of work this will probably be changed and we will ask the caller to pass in the owner UObject pointer instead and then we will process the filtering when building the package trailer to a) keep all of the filtering code in one place b) keep the filtering consistent ### PackageSubmissionChecks - The virtualization process in will now request the payloads that can be virtualized from the package trailer, which respects the new payload flag, rather than requesting all locally stored payloads. ### UObjects - There is no need for the SoundWave or MeshDescription classes to opt out of virtualization on construction. This will be done when the package is saved and is now data driven rather than being hardcoded. ### DumpPackagePayloadInfo - The command has been updated to also display the filter reasons applied to each payload [CL 20240971 by paul chipchase in ue5-main branch]
2022-05-17 07:54:28 -04:00
}
Add a config file option to allow payloads stored in .umap and associated "_builddata.uasset" files to be filtered from the virtualization process. This option defaults to true. #rb Per.Larsson #jira UE-156750 #rnx #preflight 62f212e13b773d04161ee7dd ### Problem - The payloads stored in map files tend to change more than other assets and would cause a lot more churn in the VA system. - Some other systems like the landscape component are not able to sensibly continue if their payloads cannot be accessed (heightmaps for exmaple) and would prefer not to allow virtualization. - As a short term fix we need an option to disable the virtualization on all payloads in map files. Future improvements to the filtering system will allow systems to more easily opt their payloads out of virtualization. When this is functional we might want to change the default from true to false. ### Feature - The config optionf for this filtering is "[Core.VirtualizationModule]FilterMapContent=True" - Testing if the owning UObject for a payload is in a umap can get tricky, because we not only need to check the umap but we also need to check if it is in a "_builddata.uasset" file, which is an additional file we store next to a umap containing things like lightmaps etc. - At the moment we check for this by finding the outermost object for the given owner and check to see if it is a ULevel, UWorld or UMapBuildDataRegistry. This is a bit of a kludge but the types we need to check against are not accessible by this module and making them accessible will pull in a lot of dependencies that we'd prefer not to add. -- One improvement might be to tag the FLinkerSave with the info we need and passing that into the serialization process rather than trying to work it out ourselves but I am wary of making that change until we are 100% sure that we want to keep this feature. ### Refactor - Removed IVirtualizationSystem::IsDisabledForObject and replaced it with ::FilterPayload which can return multiple reasons for preventing a payload from virtualizing. (the method was added during 5.1 development so it should be fine to just replace it without deprecation) -- The original behaviour for FVirtualizationManager::IsDisabledForObject has been moved to FVirtualizationManager::ShouldVirtualizeAsset - Added a new header to declare enums/types used by the various parts of the virtualization system and started by moving EPayloadFilterReason there from the package trailer header. This allows both the core API and PackageTrailer to use EPayloadFilterReason without creating overburdened header dependencies. -- EPayloadFilterReason has moved from the UE namespace to UE::Virtualization so the package trailer code needed updating accordingly. - EditorBulkData will ask the virtualization system for the base filter reason, then add it's own reasons if UE_ENABLE_VIRTUALIZATION_TOGGLE is enabled. This bit of code will be removed for 5.1 [CL 21283179 by paul chipchase in ue5-main branch]
2022-08-09 07:51:55 -04:00
return PayloadFilter;
It is now possible to disable virtualization for all payloads owned by a specific asset type by adding the name of the asset to [Core.ContentVirtualization]DisabledAsset string array in the engine ini file. #rb Per.Larsson #rnx #jira UE-151377 #preflight 628364050039ea57a52d6989 ### Virtualization - [Core.ContentVirtualization] in the engine ini file now supports an array called 'DisabledAsset' which can be used to name asset types that should not virtualize their payloads. -- By default (in BaseEngine.ini) we have disabled the StaticMesh asset as we know it will crash if a payload is missing and the SoundWave asset as it still is pending testing. - This new way to disable virtualization is data driven. The older hard coded method has not been removed but will likely be reworked in a future submit. - Now when an editor bulkdata is adding it's payload to the package trailer builder during package save it will poll the virtualization system with a call to the new method ::IsDisabledForObject by passing in it's owner. -- If the owner is valid and was present in the 'DisabledAsset' array then the method will return true and the EPayloadFlags::DisableVirtualization flag will be applied. ### Package Trailer - The pre-existing functionality of enum EPayloadFilter has been moved to a new enum EPayloadStorageType as will only filter payloads based on their storage type. - EPayloadFilter has been modified to filter payloads based on functionality although at the moment the only thing it can filter for is to return payloads that can be virtualized, it is left for future expansion. - EPayloadFlags has been reduced to a uint16 with the remaining 2bytes being turned into a new member EPayloadFilterReason. - This new member allows us to record the exact reason why a payload is excluded from virtualization. If it is zero then the payload can virtualize, otherwise it will contain one or more reasons as to why it is being excluded. For this reason the enum is a bitfield. - Added overloads of ::GetPayloads and ::GetNumPayloads that take EPayloadFilter rather than a EPayloadStorageType - Added wrappers around all AccessMode types for FLookupTableEntry. - FPackageTrailerBuilder has been extended to take a EPayloadFilterReason so that the caller can already provide a reason why the payload cannot be virtualized. -- As a future peace of work this will probably be changed and we will ask the caller to pass in the owner UObject pointer instead and then we will process the filtering when building the package trailer to a) keep all of the filtering code in one place b) keep the filtering consistent ### PackageSubmissionChecks - The virtualization process in will now request the payloads that can be virtualized from the package trailer, which respects the new payload flag, rather than requesting all locally stored payloads. ### UObjects - There is no need for the SoundWave or MeshDescription classes to opt out of virtualization on construction. This will be done when the package is saved and is now data driven rather than being hardcoded. ### DumpPackagePayloadInfo - The command has been updated to also display the filter reasons applied to each payload [CL 20240971 by paul chipchase in ue5-main branch]
2022-05-17 07:54:28 -04:00
}
Add an ini file option which when set to true allows package submissions to source control to go ahead even if the virtualization process failed. #rb none #jira UE-159596 #rnx #preflight 62d94160110da0f944afdd32 ### Problem - When rolling our virtualization to projects we have run into a number of set up problems which has caused users to fail to submit packages from the editor as when the virtualization failed we prevented the overall submit from going through. - Although we will eventually work through all of these problems and add better fault tolerance for now it is annoying for the content team so we need an easy way for a project to allow package submits to be completed even if the virtualization process part of the submit failed. - Worth noting that the virtualization process failing should never affect the state of the package files, the only downside is that the packages may not be virtualized. ### Fix - The virtualization/rehydration of packages now return an enum instead of a bool although at the moment we are only returning Success and Failed, but it will allow us to expand in the future - Combined the code calling the virtualization process from both the source control window and the source control changelist window into a single utility function. -- Now the two windows only diverge on how they report failure to the user. - This new utility function now checks to see if the virtualization manager suggests if failing the virtualization process should block any package submission to source control or not. - I am not happy with this solution, but I haven't come up with anything that feels right, this solution will at least work. [CL 21199597 by paul chipchase in ue5-main branch]
2022-07-21 08:31:47 -04:00
bool FVirtualizationManager::AllowSubmitIfVirtualizationFailed() const
{
return bAllowSubmitIfVirtualizationFailed;
}
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
bool FVirtualizationManager::PushData(TArrayView<FPushRequest> Requests, EStorageType StorageType)
{
TRACE_CPUPROFILER_EVENT_SCOPE(FVirtualizationManager::PushData);
Virtualizing an asset will no longer display an error message if the project has no caching storage backends set up. #rb Per.Larsson #jira UE-171492 #rnx #preflight 6391f02d67018b14b581c0b0 - It is possible that a project might want to have persistent storage enabled but no caching storage, it is probably a bad idea but it should work. However before this fix doing so would cause an error to be logged during the virtualization of a package and fail the process. - During the virtualization process we now check if pushing is enabled for cache storage before trying to push there, if not then we log that the phase is being skipped. - Even though the above fixes the problem we would still get odd results when pushing payloads to cached storage without any backends enabled. -- We now check if the pushing process is disabled before processing requests, so we can fail faster. There is now also a proper error value for this that can be stored in each request (FPushRequest) where as previously they'd all still display "pending" -- We also check to see if the requested push type has any associated backend before processing requests and have a specific error value for this. Note that we consider - We also now force the visibility of the slow task progress bar, as otherwise we might not end up displaying the virtualization progress to the progress dialog (this is a work around to a long standing problem with the slow task system due to the time limit associated with updating the dialog via EnterProgressFrame, this needs to be fixed elsewhere) #ushell-cherrypick of 23445439 by paul.chipchase [CL 23461405 by paul chipchase in ue5-main branch]
2022-12-09 03:39:20 -05:00
// No requests always counts as success
if (Requests.IsEmpty())
{
return true;
}
Virtualizing an asset will no longer display an error message if the project has no caching storage backends set up. #rb Per.Larsson #jira UE-171492 #rnx #preflight 6391f02d67018b14b581c0b0 - It is possible that a project might want to have persistent storage enabled but no caching storage, it is probably a bad idea but it should work. However before this fix doing so would cause an error to be logged during the virtualization of a package and fail the process. - During the virtualization process we now check if pushing is enabled for cache storage before trying to push there, if not then we log that the phase is being skipped. - Even though the above fixes the problem we would still get odd results when pushing payloads to cached storage without any backends enabled. -- We now check if the pushing process is disabled before processing requests, so we can fail faster. There is now also a proper error value for this that can be stored in each request (FPushRequest) where as previously they'd all still display "pending" -- We also check to see if the requested push type has any associated backend before processing requests and have a specific error value for this. Note that we consider - We also now force the visibility of the slow task progress bar, as otherwise we might not end up displaying the virtualization progress to the progress dialog (this is a work around to a long standing problem with the slow task system due to the time limit associated with updating the dialog via EnterProgressFrame, this needs to be fixed elsewhere) #ushell-cherrypick of 23445439 by paul.chipchase [CL 23461405 by paul chipchase in ue5-main branch]
2022-12-09 03:39:20 -05:00
// Attempting to virtualize when the system or process is disabled always counts as a failure
if (!IsEnabled() || !bAllowPackageVirtualization)
{
SetPushRequestsResult(Requests, FPushResult::GetAsProcessDisabled());
return false;
}
FBackendArray& Backends = IsCacheType(StorageType) ? CacheStorageBackends : PersistentStorageBackends;
if (Backends.IsEmpty())
{
SetPushRequestsResult(Requests, FPushResult::GetAsNoBackend());
return false;
}
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
TArray<FPushRequest> ValidatedRequests;
ValidatedRequests.Reserve(Requests.Num());
TArray<int32> OriginalToValidatedRequest; // Builds a mapping between Requests and ValidatedRequests for later
OriginalToValidatedRequest.SetNum(Requests.Num());
// Create a new list of FPushRequest, excluding the requests that should not be processed for what ever reason.
for (int32 Index = 0; Index < Requests.Num(); ++Index)
{
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
OriginalToValidatedRequest[Index] = INDEX_NONE;
FPushRequest& Request = Requests[Index];
When virtualizing payloads we now load the payloads from disk on demand rather than all at once. This allows us to avoid memory spikes when virtualizing large amounts of data. #rb Per.Larsson #rnx #jira UE-151000 #preflight 627271c83b2ed6f85363f53a - In the old code when submitting packages for virtualization we would load all local payloads into memory then pass them to the virtualization system to be pushed to persistent storage. This works fine for an average users submits but when resaving large projects we can have submits with thousands of packages containing gigabytes of payloads. - FPushRequest has been changed to accept either a payload directly (in the form of FCompressedBuffer) or accept a reference to a IPayloadProvider which will return the payload when asked. - Most of the existing backends make no use of the batched pushing feature and only push one payload at a time. The default implementation of this will be to ask each request one at a time for the payload and then pass it to the backend for a single push. If the IPayloadProvider is being used we will therefor only ever have one payload loaded at a time avoiding memory spikes. - The source control backend currently does implement the batched pushing feature. This backend writes each payload to disk before submitting them to perforce, so all we have to do is make sure that request one payload, write it to disk, then discard the payload to avoid memory spikes. - This change required that FPushRequest make it's members private and provide accessors to them, as the caller shouldn't need to care if the payload is loaded or comes via the provider. - NOTE that this implementation is less efficient if we have packages containing many different payloads as we will end up opening the package, parsing the trailer then load a payload many times over, where as the original code would load all payloads from the file in one go. In practice, given the overhead of the source control backend this didn't make a huge difference and is probably not worth the effort to optimize at this point. [CL 20040609 by paul chipchase in ue5-main branch]
2022-05-04 08:58:50 -04:00
if (Request.GetIdentifier().IsZero() || Request.GetPayloadSize() == 0)
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
{
Request.SetResult(FPushResult::GetAsInvalid());
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
continue;
}
When virtualizing payloads we now load the payloads from disk on demand rather than all at once. This allows us to avoid memory spikes when virtualizing large amounts of data. #rb Per.Larsson #rnx #jira UE-151000 #preflight 627271c83b2ed6f85363f53a - In the old code when submitting packages for virtualization we would load all local payloads into memory then pass them to the virtualization system to be pushed to persistent storage. This works fine for an average users submits but when resaving large projects we can have submits with thousands of packages containing gigabytes of payloads. - FPushRequest has been changed to accept either a payload directly (in the form of FCompressedBuffer) or accept a reference to a IPayloadProvider which will return the payload when asked. - Most of the existing backends make no use of the batched pushing feature and only push one payload at a time. The default implementation of this will be to ask each request one at a time for the payload and then pass it to the backend for a single push. If the IPayloadProvider is being used we will therefor only ever have one payload loaded at a time avoiding memory spikes. - The source control backend currently does implement the batched pushing feature. This backend writes each payload to disk before submitting them to perforce, so all we have to do is make sure that request one payload, write it to disk, then discard the payload to avoid memory spikes. - This change required that FPushRequest make it's members private and provide accessors to them, as the caller shouldn't need to care if the payload is loaded or comes via the provider. - NOTE that this implementation is less efficient if we have packages containing many different payloads as we will end up opening the package, parsing the trailer then load a payload many times over, where as the original code would load all payloads from the file in one go. In practice, given the overhead of the source control backend this didn't make a huge difference and is probably not worth the effort to optimize at this point. [CL 20040609 by paul chipchase in ue5-main branch]
2022-05-04 08:58:50 -04:00
if ((int64)Request.GetPayloadSize() < MinPayloadLength)
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
{
UE_LOG( LogVirtualization, Verbose, TEXT("Pushing payload (id: %s) with context ('%s') was prevented as it is smaller (%" UINT64_FMT ") than the MinPayloadLength (%" INT64_FMT ")"),
When virtualizing payloads we now load the payloads from disk on demand rather than all at once. This allows us to avoid memory spikes when virtualizing large amounts of data. #rb Per.Larsson #rnx #jira UE-151000 #preflight 627271c83b2ed6f85363f53a - In the old code when submitting packages for virtualization we would load all local payloads into memory then pass them to the virtualization system to be pushed to persistent storage. This works fine for an average users submits but when resaving large projects we can have submits with thousands of packages containing gigabytes of payloads. - FPushRequest has been changed to accept either a payload directly (in the form of FCompressedBuffer) or accept a reference to a IPayloadProvider which will return the payload when asked. - Most of the existing backends make no use of the batched pushing feature and only push one payload at a time. The default implementation of this will be to ask each request one at a time for the payload and then pass it to the backend for a single push. If the IPayloadProvider is being used we will therefor only ever have one payload loaded at a time avoiding memory spikes. - The source control backend currently does implement the batched pushing feature. This backend writes each payload to disk before submitting them to perforce, so all we have to do is make sure that request one payload, write it to disk, then discard the payload to avoid memory spikes. - This change required that FPushRequest make it's members private and provide accessors to them, as the caller shouldn't need to care if the payload is loaded or comes via the provider. - NOTE that this implementation is less efficient if we have packages containing many different payloads as we will end up opening the package, parsing the trailer then load a payload many times over, where as the original code would load all payloads from the file in one go. In practice, given the overhead of the source control backend this didn't make a huge difference and is probably not worth the effort to optimize at this point. [CL 20040609 by paul chipchase in ue5-main branch]
2022-05-04 08:58:50 -04:00
*LexToString(Request.GetIdentifier()),
*Request.GetContext(),
Request.GetPayloadSize(),
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
MinPayloadLength);
Request.SetResult(FPushResult::GetAsFiltered(EPayloadFilterReason::MinSize));
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
continue;
}
When virtualizing payloads we now load the payloads from disk on demand rather than all at once. This allows us to avoid memory spikes when virtualizing large amounts of data. #rb Per.Larsson #rnx #jira UE-151000 #preflight 627271c83b2ed6f85363f53a - In the old code when submitting packages for virtualization we would load all local payloads into memory then pass them to the virtualization system to be pushed to persistent storage. This works fine for an average users submits but when resaving large projects we can have submits with thousands of packages containing gigabytes of payloads. - FPushRequest has been changed to accept either a payload directly (in the form of FCompressedBuffer) or accept a reference to a IPayloadProvider which will return the payload when asked. - Most of the existing backends make no use of the batched pushing feature and only push one payload at a time. The default implementation of this will be to ask each request one at a time for the payload and then pass it to the backend for a single push. If the IPayloadProvider is being used we will therefor only ever have one payload loaded at a time avoiding memory spikes. - The source control backend currently does implement the batched pushing feature. This backend writes each payload to disk before submitting them to perforce, so all we have to do is make sure that request one payload, write it to disk, then discard the payload to avoid memory spikes. - This change required that FPushRequest make it's members private and provide accessors to them, as the caller shouldn't need to care if the payload is loaded or comes via the provider. - NOTE that this implementation is less efficient if we have packages containing many different payloads as we will end up opening the package, parsing the trailer then load a payload many times over, where as the original code would load all payloads from the file in one go. In practice, given the overhead of the source control backend this didn't make a huge difference and is probably not worth the effort to optimize at this point. [CL 20040609 by paul chipchase in ue5-main branch]
2022-05-04 08:58:50 -04:00
if (!ShouldVirtualize(Request.GetContext()))
{
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
UE_LOG( LogVirtualization, Verbose, TEXT("Pushing payload (id: %s) with context ('%s') was prevented by filtering"),
When virtualizing payloads we now load the payloads from disk on demand rather than all at once. This allows us to avoid memory spikes when virtualizing large amounts of data. #rb Per.Larsson #rnx #jira UE-151000 #preflight 627271c83b2ed6f85363f53a - In the old code when submitting packages for virtualization we would load all local payloads into memory then pass them to the virtualization system to be pushed to persistent storage. This works fine for an average users submits but when resaving large projects we can have submits with thousands of packages containing gigabytes of payloads. - FPushRequest has been changed to accept either a payload directly (in the form of FCompressedBuffer) or accept a reference to a IPayloadProvider which will return the payload when asked. - Most of the existing backends make no use of the batched pushing feature and only push one payload at a time. The default implementation of this will be to ask each request one at a time for the payload and then pass it to the backend for a single push. If the IPayloadProvider is being used we will therefor only ever have one payload loaded at a time avoiding memory spikes. - The source control backend currently does implement the batched pushing feature. This backend writes each payload to disk before submitting them to perforce, so all we have to do is make sure that request one payload, write it to disk, then discard the payload to avoid memory spikes. - This change required that FPushRequest make it's members private and provide accessors to them, as the caller shouldn't need to care if the payload is loaded or comes via the provider. - NOTE that this implementation is less efficient if we have packages containing many different payloads as we will end up opening the package, parsing the trailer then load a payload many times over, where as the original code would load all payloads from the file in one go. In practice, given the overhead of the source control backend this didn't make a huge difference and is probably not worth the effort to optimize at this point. [CL 20040609 by paul chipchase in ue5-main branch]
2022-05-04 08:58:50 -04:00
*LexToString(Request.GetIdentifier()),
*Request.GetContext());
Request.SetResult(FPushResult::GetAsFiltered(EPayloadFilterReason::Path));
continue;
}
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
OriginalToValidatedRequest[Index] = ValidatedRequests.Num();
ValidatedRequests.Add(Request);
}
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
// Early out if none of the requests require pushing after validation
if (ValidatedRequests.IsEmpty())
{
return true;
}
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
EnsureBackendConnections();
FConditionalScopeLock _(&DebugValues.ForceSingleThreadedCS, DebugValues.bSingleThreaded);
// TODO: Note that all push operations are currently synchronous, probably
// should change to async at some point, although this makes handling failed
// pushed much more difficult.
int32 ErrorCount = 0;
bool bWasPayloadPushed = false;
Virtualizing an asset will no longer display an error message if the project has no caching storage backends set up. #rb Per.Larsson #jira UE-171492 #rnx #preflight 6391f02d67018b14b581c0b0 - It is possible that a project might want to have persistent storage enabled but no caching storage, it is probably a bad idea but it should work. However before this fix doing so would cause an error to be logged during the virtualization of a package and fail the process. - During the virtualization process we now check if pushing is enabled for cache storage before trying to push there, if not then we log that the phase is being skipped. - Even though the above fixes the problem we would still get odd results when pushing payloads to cached storage without any backends enabled. -- We now check if the pushing process is disabled before processing requests, so we can fail faster. There is now also a proper error value for this that can be stored in each request (FPushRequest) where as previously they'd all still display "pending" -- We also check to see if the requested push type has any associated backend before processing requests and have a specific error value for this. Note that we consider - We also now force the visibility of the slow task progress bar, as otherwise we might not end up displaying the virtualization progress to the progress dialog (this is a work around to a long standing problem with the slow task system due to the time limit associated with updating the dialog via EnterProgressFrame, this needs to be fixed elsewhere) #ushell-cherrypick of 23445439 by paul.chipchase [CL 23461405 by paul chipchase in ue5-main branch]
2022-12-09 03:39:20 -05:00
for (IVirtualizationBackend* Backend : Backends)
{
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
if (Backend->GetConnectionStatus() != IVirtualizationBackend::EConnectionStatus::Connected)
{
UE_LOG(LogVirtualization, Verbose, TEXT("Cannot push to backend '%s' as it is not connected"), *Backend->GetDebugName());
continue;
}
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
const bool bResult = TryPushDataToBackend(*Backend, ValidatedRequests);
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
UE_CLOG(bResult == true, LogVirtualization, Verbose, TEXT("[%s] Pushed '%d' payload(s)"), *Backend->GetDebugName(), ValidatedRequests.Num());
UE_CLOG(bResult == false, LogVirtualization, Error, TEXT("[%s] Failed to push '%d' payload(s)"), *Backend->GetDebugName(), ValidatedRequests.Num());
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
if (!bResult)
{
ErrorCount++;
}
// Debug operation to validate that the payload we just pushed can be retrieved from storage
if (DebugValues.bValidateAfterPush && bResult == true && Backend->IsOperationSupported(IVirtualizationBackend::EOperations::Pull))
{
for (FPushRequest& PushRequest : ValidatedRequests)
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
{
FPullRequest PullRequest(PushRequest.GetIdentifier());
PullDataFromBackend(*Backend, MakeArrayView(&PullRequest, 1));
checkf(PushRequest.GetIdentifier() == PullRequest.GetPayload().GetRawHash(),
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
TEXT("[%s] Failed to pull payload '%s' after it was pushed to backend"),
*Backend->GetDebugName(),
*LexToString(PushRequest.GetIdentifier()));
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
}
}
}
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
UE_CLOG(ErrorCount == Backends.Num(), LogVirtualization, Error, TEXT("Failed to push '%d' payload(s) to any backend'"), ValidatedRequests.Num());
// Now we need to update the statuses of the original list of requests with those from our validated list
for (int32 Index = 0; Index < Requests.Num(); ++Index)
{
const int32 MappingIndex = OriginalToValidatedRequest[Index];
if (MappingIndex != INDEX_NONE)
{
Requests[Index].SetResult(ValidatedRequests[MappingIndex].GetResult());
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
}
}
// For local storage we consider the push to have failed only if ALL backends gave an error, if at least one backend succeeded then the operation succeeded.
// For persistent storage we require that all backends succeeded, so any errors will fail the push operation.
return IsCacheType(StorageType) ? ErrorCount < Backends.Num() : ErrorCount == 0;
}
bool FVirtualizationManager::PullData(TArrayView<FPullRequest> Requests)
{
TRACE_CPUPROFILER_EVENT_SCOPE(FVirtualizationManager::PullData);
if (PullEnabledBackends.IsEmpty())
{
// TODO: See below, should errors here be fatal?
UE_LOG(LogVirtualization, Error, TEXT("Failed to pull payload(s) as there are no backends mounted!'"));
return false;
}
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
EnsureBackendConnections();
FConditionalScopeLock _(&DebugValues.ForceSingleThreadedCS, DebugValues.bSingleThreaded);
BroadcastEvent(Requests, IVirtualizationSystem::PullBegunNotification);
PullDataFromAllBackends(Requests);
BroadcastEvent(Requests, IVirtualizationSystem::PullEndedNotification);
bool bSuccess = true;
for (const FPullRequest& Request : Requests)
{
// Report failed pulls of valid identifiers
if (!Request.IsSuccess() && !Request.GetIdentifier().IsZero())
{
GetNotificationEvent().Broadcast(IVirtualizationSystem::PullFailedNotification, Request.GetIdentifier());
// TODO: Maybe this should be a fatal error? If we keep it as an error we need to make sure any calling
// code handles it properly.
// Could be worth extending ::PullData to return error codes instead so we can make a better distinction
// between the payload not being found in any of the backends and one or more of the backends failing.
UE_LOG(LogVirtualization, Error, TEXT("Payload '%s' failed to be pulled from any backend'"), *LexToString(Request.GetIdentifier()));
bSuccess = false;
}
if (Request.IsSuccess())
{
checkf(Request.GetIdentifier() == Request.GetPayload().GetRawHash(), TEXT("[%s] Invalid payload for '%s'"), *LexToString(Request.GetIdentifier()));
}
}
return bSuccess;
}
EQueryResult FVirtualizationManager::QueryPayloadStatuses(TArrayView<const FIoHash> Ids, EStorageType StorageType, TArray<EPayloadStatus>& OutStatuses)
Submitting packages on projects with virtualization enabled is much faster when none of the payloads actually needs to be virtualized. #rb PJ.Kack #rnx #preflight 61a795773c29b3cf13cd8250 ### PackageSubmissionChecks - Under the old model submitting a large number of packages could be very slow as each package would check each payload that it owns and is currently stored locally one at a time. For the source control backend this created quite a large overhead even when all of the payloads were already virtualized. - Now we do a pass over the submitted files to find all valid packages that have package trailers with locally stored payloads, gather the payloads into a single list and then query that in one large batch. - Once we find which payloads are not in permanent storage (note that in the case where a project is using multiple permanent storage solutions, if a payload is missing in one backend it counts as not being in permanent storage) we then attempt to virtualized them. - Only after all of this is done will we create the truncated copy of each package and then append the updated trailer to each one. In theory doing it in this order this might slightly increase the change of submit failures that occur after virtualization that result in a package never being submitted and orphaned payloads being added to permanent storage, but this will always be a risk. - Added an assert to fire if we detect a trailer with some virtualized and some local payloads. This should be a supported feature but needs proper testing first before we can allow it. With out current project settings no project should actually encounter this scenario. - To make the code easier to follow we now early out of the entire check when errors are encountered. - Added logging at various stages in the process to help show the user that something is happening and make problems easier to identify in the future. - Notes -- There is a lot of handling of invalid FPayloads. This is because it is currently possible to add empty payloads to the trailer which is inefficient and wastes space. The trailer will be modified to reject empty payloads in a future update at which point a lot of this handling can be removed. -- This could've also been solved by not fully rehydrating a package on save by the end user, which will be added as a project setting in a future piece of work, but this approach will solve the edge case when the user does have a large amount of hydrated packages which contain payloads that are already virtualized so it was better to fix that now while we have good test cases for it. -- We still have scaling problems with large number of package being submitted that do have payloads that need to be virtualized, this will be fixed by extending IVirtualizationSystem::Push to also accept batches of payloads in future work. -- OnPrePackageSubmission could be broken up into smaller chunks to make the code easier to follow. This will be done after the batch payload submission work is done. ### VirtualizationSystem - EStorageType has been promoted to enum class. - Added a new enum FPayloadStatus to be used when querying if a payload exists in a backend storage system or not. - Add a new method ::DoPayloadsExist which allows the caller to query if one or more payloads exists in the given backend storage system. ### VirtualizationManager - Implemented ::DoPayloadsExist. First we get the results from each backend in the storage system (which return as true or false from each backend) then total how many backends found the payload in order to set the correct status. ### IVirtualizationBackend - ::DoesPayloadExist which queries the existence of a single payload has been added to the interface. Most backends already implemented this for private use and if so have had their implementation renamed to match this. - Also added ::DoPayloadsExist which takes a batch of FpayloadIdsto query. Some backends can deal with a batch of payload ids much more efficiently than one at a time, although the default implementation does call ::DoesPayloadExist for each requested payload. -- The default implementation prevents every backend from needing to implement the same for loop but does allow backends that can gain from batching to override it. ### VirtualizationSourceControlBackend - This backend does override ::DoPayloadsExist and implements it's own version as it tends to perform very poorly when not operating on larger batches. - In this case ::DoesPayloadExist calls back to ::DoPayloadsExist to check each payload rather than implement as specific version. ### PackageTrailer - The trailer can now be queries to request how many payloads of a given type it contains #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18339847 in //UE5/Release-5.0/... via CL 18339852 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18339859 by paul chipchase in ue5-release-engine-test branch]
2021-12-01 11:13:31 -05:00
{
TRACE_CPUPROFILER_EVENT_SCOPE(FVirtualizationManager::DoPayloadsExist);
OutStatuses.SetNum(Ids.Num()); // Make sure we set the number out statuses before we potentially early out
if (Ids.IsEmpty())
{
return EQueryResult::Success;
}
Submitting packages on projects with virtualization enabled is much faster when none of the payloads actually needs to be virtualized. #rb PJ.Kack #rnx #preflight 61a795773c29b3cf13cd8250 ### PackageSubmissionChecks - Under the old model submitting a large number of packages could be very slow as each package would check each payload that it owns and is currently stored locally one at a time. For the source control backend this created quite a large overhead even when all of the payloads were already virtualized. - Now we do a pass over the submitted files to find all valid packages that have package trailers with locally stored payloads, gather the payloads into a single list and then query that in one large batch. - Once we find which payloads are not in permanent storage (note that in the case where a project is using multiple permanent storage solutions, if a payload is missing in one backend it counts as not being in permanent storage) we then attempt to virtualized them. - Only after all of this is done will we create the truncated copy of each package and then append the updated trailer to each one. In theory doing it in this order this might slightly increase the change of submit failures that occur after virtualization that result in a package never being submitted and orphaned payloads being added to permanent storage, but this will always be a risk. - Added an assert to fire if we detect a trailer with some virtualized and some local payloads. This should be a supported feature but needs proper testing first before we can allow it. With out current project settings no project should actually encounter this scenario. - To make the code easier to follow we now early out of the entire check when errors are encountered. - Added logging at various stages in the process to help show the user that something is happening and make problems easier to identify in the future. - Notes -- There is a lot of handling of invalid FPayloads. This is because it is currently possible to add empty payloads to the trailer which is inefficient and wastes space. The trailer will be modified to reject empty payloads in a future update at which point a lot of this handling can be removed. -- This could've also been solved by not fully rehydrating a package on save by the end user, which will be added as a project setting in a future piece of work, but this approach will solve the edge case when the user does have a large amount of hydrated packages which contain payloads that are already virtualized so it was better to fix that now while we have good test cases for it. -- We still have scaling problems with large number of package being submitted that do have payloads that need to be virtualized, this will be fixed by extending IVirtualizationSystem::Push to also accept batches of payloads in future work. -- OnPrePackageSubmission could be broken up into smaller chunks to make the code easier to follow. This will be done after the batch payload submission work is done. ### VirtualizationSystem - EStorageType has been promoted to enum class. - Added a new enum FPayloadStatus to be used when querying if a payload exists in a backend storage system or not. - Add a new method ::DoPayloadsExist which allows the caller to query if one or more payloads exists in the given backend storage system. ### VirtualizationManager - Implemented ::DoPayloadsExist. First we get the results from each backend in the storage system (which return as true or false from each backend) then total how many backends found the payload in order to set the correct status. ### IVirtualizationBackend - ::DoesPayloadExist which queries the existence of a single payload has been added to the interface. Most backends already implemented this for private use and if so have had their implementation renamed to match this. - Also added ::DoPayloadsExist which takes a batch of FpayloadIdsto query. Some backends can deal with a batch of payload ids much more efficiently than one at a time, although the default implementation does call ::DoesPayloadExist for each requested payload. -- The default implementation prevents every backend from needing to implement the same for loop but does allow backends that can gain from batching to override it. ### VirtualizationSourceControlBackend - This backend does override ::DoPayloadsExist and implements it's own version as it tends to perform very poorly when not operating on larger batches. - In this case ::DoesPayloadExist calls back to ::DoPayloadsExist to check each payload rather than implement as specific version. ### PackageTrailer - The trailer can now be queries to request how many payloads of a given type it contains #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18339847 in //UE5/Release-5.0/... via CL 18339852 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18339859 by paul chipchase in ue5-release-engine-test branch]
2021-12-01 11:13:31 -05:00
for (int32 Index = 0; Index < Ids.Num(); ++Index)
{
OutStatuses[Index] = Ids[Index].IsZero() ? EPayloadStatus::Invalid : EPayloadStatus::NotFound;
Submitting packages on projects with virtualization enabled is much faster when none of the payloads actually needs to be virtualized. #rb PJ.Kack #rnx #preflight 61a795773c29b3cf13cd8250 ### PackageSubmissionChecks - Under the old model submitting a large number of packages could be very slow as each package would check each payload that it owns and is currently stored locally one at a time. For the source control backend this created quite a large overhead even when all of the payloads were already virtualized. - Now we do a pass over the submitted files to find all valid packages that have package trailers with locally stored payloads, gather the payloads into a single list and then query that in one large batch. - Once we find which payloads are not in permanent storage (note that in the case where a project is using multiple permanent storage solutions, if a payload is missing in one backend it counts as not being in permanent storage) we then attempt to virtualized them. - Only after all of this is done will we create the truncated copy of each package and then append the updated trailer to each one. In theory doing it in this order this might slightly increase the change of submit failures that occur after virtualization that result in a package never being submitted and orphaned payloads being added to permanent storage, but this will always be a risk. - Added an assert to fire if we detect a trailer with some virtualized and some local payloads. This should be a supported feature but needs proper testing first before we can allow it. With out current project settings no project should actually encounter this scenario. - To make the code easier to follow we now early out of the entire check when errors are encountered. - Added logging at various stages in the process to help show the user that something is happening and make problems easier to identify in the future. - Notes -- There is a lot of handling of invalid FPayloads. This is because it is currently possible to add empty payloads to the trailer which is inefficient and wastes space. The trailer will be modified to reject empty payloads in a future update at which point a lot of this handling can be removed. -- This could've also been solved by not fully rehydrating a package on save by the end user, which will be added as a project setting in a future piece of work, but this approach will solve the edge case when the user does have a large amount of hydrated packages which contain payloads that are already virtualized so it was better to fix that now while we have good test cases for it. -- We still have scaling problems with large number of package being submitted that do have payloads that need to be virtualized, this will be fixed by extending IVirtualizationSystem::Push to also accept batches of payloads in future work. -- OnPrePackageSubmission could be broken up into smaller chunks to make the code easier to follow. This will be done after the batch payload submission work is done. ### VirtualizationSystem - EStorageType has been promoted to enum class. - Added a new enum FPayloadStatus to be used when querying if a payload exists in a backend storage system or not. - Add a new method ::DoPayloadsExist which allows the caller to query if one or more payloads exists in the given backend storage system. ### VirtualizationManager - Implemented ::DoPayloadsExist. First we get the results from each backend in the storage system (which return as true or false from each backend) then total how many backends found the payload in order to set the correct status. ### IVirtualizationBackend - ::DoesPayloadExist which queries the existence of a single payload has been added to the interface. Most backends already implemented this for private use and if so have had their implementation renamed to match this. - Also added ::DoPayloadsExist which takes a batch of FpayloadIdsto query. Some backends can deal with a batch of payload ids much more efficiently than one at a time, although the default implementation does call ::DoesPayloadExist for each requested payload. -- The default implementation prevents every backend from needing to implement the same for loop but does allow backends that can gain from batching to override it. ### VirtualizationSourceControlBackend - This backend does override ::DoPayloadsExist and implements it's own version as it tends to perform very poorly when not operating on larger batches. - In this case ::DoesPayloadExist calls back to ::DoPayloadsExist to check each payload rather than implement as specific version. ### PackageTrailer - The trailer can now be queries to request how many payloads of a given type it contains #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18339847 in //UE5/Release-5.0/... via CL 18339852 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18339859 by paul chipchase in ue5-release-engine-test branch]
2021-12-01 11:13:31 -05:00
}
FBackendArray& Backends = IsCacheType(StorageType) ? CacheStorageBackends : PersistentStorageBackends;
Submitting packages on projects with virtualization enabled is much faster when none of the payloads actually needs to be virtualized. #rb PJ.Kack #rnx #preflight 61a795773c29b3cf13cd8250 ### PackageSubmissionChecks - Under the old model submitting a large number of packages could be very slow as each package would check each payload that it owns and is currently stored locally one at a time. For the source control backend this created quite a large overhead even when all of the payloads were already virtualized. - Now we do a pass over the submitted files to find all valid packages that have package trailers with locally stored payloads, gather the payloads into a single list and then query that in one large batch. - Once we find which payloads are not in permanent storage (note that in the case where a project is using multiple permanent storage solutions, if a payload is missing in one backend it counts as not being in permanent storage) we then attempt to virtualized them. - Only after all of this is done will we create the truncated copy of each package and then append the updated trailer to each one. In theory doing it in this order this might slightly increase the change of submit failures that occur after virtualization that result in a package never being submitted and orphaned payloads being added to permanent storage, but this will always be a risk. - Added an assert to fire if we detect a trailer with some virtualized and some local payloads. This should be a supported feature but needs proper testing first before we can allow it. With out current project settings no project should actually encounter this scenario. - To make the code easier to follow we now early out of the entire check when errors are encountered. - Added logging at various stages in the process to help show the user that something is happening and make problems easier to identify in the future. - Notes -- There is a lot of handling of invalid FPayloads. This is because it is currently possible to add empty payloads to the trailer which is inefficient and wastes space. The trailer will be modified to reject empty payloads in a future update at which point a lot of this handling can be removed. -- This could've also been solved by not fully rehydrating a package on save by the end user, which will be added as a project setting in a future piece of work, but this approach will solve the edge case when the user does have a large amount of hydrated packages which contain payloads that are already virtualized so it was better to fix that now while we have good test cases for it. -- We still have scaling problems with large number of package being submitted that do have payloads that need to be virtualized, this will be fixed by extending IVirtualizationSystem::Push to also accept batches of payloads in future work. -- OnPrePackageSubmission could be broken up into smaller chunks to make the code easier to follow. This will be done after the batch payload submission work is done. ### VirtualizationSystem - EStorageType has been promoted to enum class. - Added a new enum FPayloadStatus to be used when querying if a payload exists in a backend storage system or not. - Add a new method ::DoPayloadsExist which allows the caller to query if one or more payloads exists in the given backend storage system. ### VirtualizationManager - Implemented ::DoPayloadsExist. First we get the results from each backend in the storage system (which return as true or false from each backend) then total how many backends found the payload in order to set the correct status. ### IVirtualizationBackend - ::DoesPayloadExist which queries the existence of a single payload has been added to the interface. Most backends already implemented this for private use and if so have had their implementation renamed to match this. - Also added ::DoPayloadsExist which takes a batch of FpayloadIdsto query. Some backends can deal with a batch of payload ids much more efficiently than one at a time, although the default implementation does call ::DoesPayloadExist for each requested payload. -- The default implementation prevents every backend from needing to implement the same for loop but does allow backends that can gain from batching to override it. ### VirtualizationSourceControlBackend - This backend does override ::DoPayloadsExist and implements it's own version as it tends to perform very poorly when not operating on larger batches. - In this case ::DoesPayloadExist calls back to ::DoPayloadsExist to check each payload rather than implement as specific version. ### PackageTrailer - The trailer can now be queries to request how many payloads of a given type it contains #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18339847 in //UE5/Release-5.0/... via CL 18339852 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18339859 by paul chipchase in ue5-release-engine-test branch]
2021-12-01 11:13:31 -05:00
TArray<int8> HitCount;
TArray<bool> Results;
HitCount.SetNum(Ids.Num());
Results.SetNum(Ids.Num());
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
EnsureBackendConnections();
Submitting packages on projects with virtualization enabled is much faster when none of the payloads actually needs to be virtualized. #rb PJ.Kack #rnx #preflight 61a795773c29b3cf13cd8250 ### PackageSubmissionChecks - Under the old model submitting a large number of packages could be very slow as each package would check each payload that it owns and is currently stored locally one at a time. For the source control backend this created quite a large overhead even when all of the payloads were already virtualized. - Now we do a pass over the submitted files to find all valid packages that have package trailers with locally stored payloads, gather the payloads into a single list and then query that in one large batch. - Once we find which payloads are not in permanent storage (note that in the case where a project is using multiple permanent storage solutions, if a payload is missing in one backend it counts as not being in permanent storage) we then attempt to virtualized them. - Only after all of this is done will we create the truncated copy of each package and then append the updated trailer to each one. In theory doing it in this order this might slightly increase the change of submit failures that occur after virtualization that result in a package never being submitted and orphaned payloads being added to permanent storage, but this will always be a risk. - Added an assert to fire if we detect a trailer with some virtualized and some local payloads. This should be a supported feature but needs proper testing first before we can allow it. With out current project settings no project should actually encounter this scenario. - To make the code easier to follow we now early out of the entire check when errors are encountered. - Added logging at various stages in the process to help show the user that something is happening and make problems easier to identify in the future. - Notes -- There is a lot of handling of invalid FPayloads. This is because it is currently possible to add empty payloads to the trailer which is inefficient and wastes space. The trailer will be modified to reject empty payloads in a future update at which point a lot of this handling can be removed. -- This could've also been solved by not fully rehydrating a package on save by the end user, which will be added as a project setting in a future piece of work, but this approach will solve the edge case when the user does have a large amount of hydrated packages which contain payloads that are already virtualized so it was better to fix that now while we have good test cases for it. -- We still have scaling problems with large number of package being submitted that do have payloads that need to be virtualized, this will be fixed by extending IVirtualizationSystem::Push to also accept batches of payloads in future work. -- OnPrePackageSubmission could be broken up into smaller chunks to make the code easier to follow. This will be done after the batch payload submission work is done. ### VirtualizationSystem - EStorageType has been promoted to enum class. - Added a new enum FPayloadStatus to be used when querying if a payload exists in a backend storage system or not. - Add a new method ::DoPayloadsExist which allows the caller to query if one or more payloads exists in the given backend storage system. ### VirtualizationManager - Implemented ::DoPayloadsExist. First we get the results from each backend in the storage system (which return as true or false from each backend) then total how many backends found the payload in order to set the correct status. ### IVirtualizationBackend - ::DoesPayloadExist which queries the existence of a single payload has been added to the interface. Most backends already implemented this for private use and if so have had their implementation renamed to match this. - Also added ::DoPayloadsExist which takes a batch of FpayloadIdsto query. Some backends can deal with a batch of payload ids much more efficiently than one at a time, although the default implementation does call ::DoesPayloadExist for each requested payload. -- The default implementation prevents every backend from needing to implement the same for loop but does allow backends that can gain from batching to override it. ### VirtualizationSourceControlBackend - This backend does override ::DoPayloadsExist and implements it's own version as it tends to perform very poorly when not operating on larger batches. - In this case ::DoesPayloadExist calls back to ::DoPayloadsExist to check each payload rather than implement as specific version. ### PackageTrailer - The trailer can now be queries to request how many payloads of a given type it contains #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18339847 in //UE5/Release-5.0/... via CL 18339852 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18339859 by paul chipchase in ue5-release-engine-test branch]
2021-12-01 11:13:31 -05:00
{
FConditionalScopeLock _(&DebugValues.ForceSingleThreadedCS, DebugValues.bSingleThreaded);
Submitting packages on projects with virtualization enabled is much faster when none of the payloads actually needs to be virtualized. #rb PJ.Kack #rnx #preflight 61a795773c29b3cf13cd8250 ### PackageSubmissionChecks - Under the old model submitting a large number of packages could be very slow as each package would check each payload that it owns and is currently stored locally one at a time. For the source control backend this created quite a large overhead even when all of the payloads were already virtualized. - Now we do a pass over the submitted files to find all valid packages that have package trailers with locally stored payloads, gather the payloads into a single list and then query that in one large batch. - Once we find which payloads are not in permanent storage (note that in the case where a project is using multiple permanent storage solutions, if a payload is missing in one backend it counts as not being in permanent storage) we then attempt to virtualized them. - Only after all of this is done will we create the truncated copy of each package and then append the updated trailer to each one. In theory doing it in this order this might slightly increase the change of submit failures that occur after virtualization that result in a package never being submitted and orphaned payloads being added to permanent storage, but this will always be a risk. - Added an assert to fire if we detect a trailer with some virtualized and some local payloads. This should be a supported feature but needs proper testing first before we can allow it. With out current project settings no project should actually encounter this scenario. - To make the code easier to follow we now early out of the entire check when errors are encountered. - Added logging at various stages in the process to help show the user that something is happening and make problems easier to identify in the future. - Notes -- There is a lot of handling of invalid FPayloads. This is because it is currently possible to add empty payloads to the trailer which is inefficient and wastes space. The trailer will be modified to reject empty payloads in a future update at which point a lot of this handling can be removed. -- This could've also been solved by not fully rehydrating a package on save by the end user, which will be added as a project setting in a future piece of work, but this approach will solve the edge case when the user does have a large amount of hydrated packages which contain payloads that are already virtualized so it was better to fix that now while we have good test cases for it. -- We still have scaling problems with large number of package being submitted that do have payloads that need to be virtualized, this will be fixed by extending IVirtualizationSystem::Push to also accept batches of payloads in future work. -- OnPrePackageSubmission could be broken up into smaller chunks to make the code easier to follow. This will be done after the batch payload submission work is done. ### VirtualizationSystem - EStorageType has been promoted to enum class. - Added a new enum FPayloadStatus to be used when querying if a payload exists in a backend storage system or not. - Add a new method ::DoPayloadsExist which allows the caller to query if one or more payloads exists in the given backend storage system. ### VirtualizationManager - Implemented ::DoPayloadsExist. First we get the results from each backend in the storage system (which return as true or false from each backend) then total how many backends found the payload in order to set the correct status. ### IVirtualizationBackend - ::DoesPayloadExist which queries the existence of a single payload has been added to the interface. Most backends already implemented this for private use and if so have had their implementation renamed to match this. - Also added ::DoPayloadsExist which takes a batch of FpayloadIdsto query. Some backends can deal with a batch of payload ids much more efficiently than one at a time, although the default implementation does call ::DoesPayloadExist for each requested payload. -- The default implementation prevents every backend from needing to implement the same for loop but does allow backends that can gain from batching to override it. ### VirtualizationSourceControlBackend - This backend does override ::DoPayloadsExist and implements it's own version as it tends to perform very poorly when not operating on larger batches. - In this case ::DoesPayloadExist calls back to ::DoPayloadsExist to check each payload rather than implement as specific version. ### PackageTrailer - The trailer can now be queries to request how many payloads of a given type it contains #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18339847 in //UE5/Release-5.0/... via CL 18339852 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18339859 by paul chipchase in ue5-release-engine-test branch]
2021-12-01 11:13:31 -05:00
for (IVirtualizationBackend* Backend : Backends)
{
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
if (Backend->GetConnectionStatus() != IVirtualizationBackend::EConnectionStatus::Connected)
{
UE_LOG(LogVirtualization, Verbose, TEXT("Cannot query backend '%s' as it is not connected"), *Backend->GetDebugName());
continue;
}
Submitting packages on projects with virtualization enabled is much faster when none of the payloads actually needs to be virtualized. #rb PJ.Kack #rnx #preflight 61a795773c29b3cf13cd8250 ### PackageSubmissionChecks - Under the old model submitting a large number of packages could be very slow as each package would check each payload that it owns and is currently stored locally one at a time. For the source control backend this created quite a large overhead even when all of the payloads were already virtualized. - Now we do a pass over the submitted files to find all valid packages that have package trailers with locally stored payloads, gather the payloads into a single list and then query that in one large batch. - Once we find which payloads are not in permanent storage (note that in the case where a project is using multiple permanent storage solutions, if a payload is missing in one backend it counts as not being in permanent storage) we then attempt to virtualized them. - Only after all of this is done will we create the truncated copy of each package and then append the updated trailer to each one. In theory doing it in this order this might slightly increase the change of submit failures that occur after virtualization that result in a package never being submitted and orphaned payloads being added to permanent storage, but this will always be a risk. - Added an assert to fire if we detect a trailer with some virtualized and some local payloads. This should be a supported feature but needs proper testing first before we can allow it. With out current project settings no project should actually encounter this scenario. - To make the code easier to follow we now early out of the entire check when errors are encountered. - Added logging at various stages in the process to help show the user that something is happening and make problems easier to identify in the future. - Notes -- There is a lot of handling of invalid FPayloads. This is because it is currently possible to add empty payloads to the trailer which is inefficient and wastes space. The trailer will be modified to reject empty payloads in a future update at which point a lot of this handling can be removed. -- This could've also been solved by not fully rehydrating a package on save by the end user, which will be added as a project setting in a future piece of work, but this approach will solve the edge case when the user does have a large amount of hydrated packages which contain payloads that are already virtualized so it was better to fix that now while we have good test cases for it. -- We still have scaling problems with large number of package being submitted that do have payloads that need to be virtualized, this will be fixed by extending IVirtualizationSystem::Push to also accept batches of payloads in future work. -- OnPrePackageSubmission could be broken up into smaller chunks to make the code easier to follow. This will be done after the batch payload submission work is done. ### VirtualizationSystem - EStorageType has been promoted to enum class. - Added a new enum FPayloadStatus to be used when querying if a payload exists in a backend storage system or not. - Add a new method ::DoPayloadsExist which allows the caller to query if one or more payloads exists in the given backend storage system. ### VirtualizationManager - Implemented ::DoPayloadsExist. First we get the results from each backend in the storage system (which return as true or false from each backend) then total how many backends found the payload in order to set the correct status. ### IVirtualizationBackend - ::DoesPayloadExist which queries the existence of a single payload has been added to the interface. Most backends already implemented this for private use and if so have had their implementation renamed to match this. - Also added ::DoPayloadsExist which takes a batch of FpayloadIdsto query. Some backends can deal with a batch of payload ids much more efficiently than one at a time, although the default implementation does call ::DoesPayloadExist for each requested payload. -- The default implementation prevents every backend from needing to implement the same for loop but does allow backends that can gain from batching to override it. ### VirtualizationSourceControlBackend - This backend does override ::DoPayloadsExist and implements it's own version as it tends to perform very poorly when not operating on larger batches. - In this case ::DoesPayloadExist calls back to ::DoPayloadsExist to check each payload rather than implement as specific version. ### PackageTrailer - The trailer can now be queries to request how many payloads of a given type it contains #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18339847 in //UE5/Release-5.0/... via CL 18339852 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18339859 by paul chipchase in ue5-release-engine-test branch]
2021-12-01 11:13:31 -05:00
if (!Backend->DoPayloadsExist(Ids, Results))
{
// If a backend entirely failed we should early out and report the problem
OutStatuses.Reset();
return EQueryResult::Failure_Unknown;
Submitting packages on projects with virtualization enabled is much faster when none of the payloads actually needs to be virtualized. #rb PJ.Kack #rnx #preflight 61a795773c29b3cf13cd8250 ### PackageSubmissionChecks - Under the old model submitting a large number of packages could be very slow as each package would check each payload that it owns and is currently stored locally one at a time. For the source control backend this created quite a large overhead even when all of the payloads were already virtualized. - Now we do a pass over the submitted files to find all valid packages that have package trailers with locally stored payloads, gather the payloads into a single list and then query that in one large batch. - Once we find which payloads are not in permanent storage (note that in the case where a project is using multiple permanent storage solutions, if a payload is missing in one backend it counts as not being in permanent storage) we then attempt to virtualized them. - Only after all of this is done will we create the truncated copy of each package and then append the updated trailer to each one. In theory doing it in this order this might slightly increase the change of submit failures that occur after virtualization that result in a package never being submitted and orphaned payloads being added to permanent storage, but this will always be a risk. - Added an assert to fire if we detect a trailer with some virtualized and some local payloads. This should be a supported feature but needs proper testing first before we can allow it. With out current project settings no project should actually encounter this scenario. - To make the code easier to follow we now early out of the entire check when errors are encountered. - Added logging at various stages in the process to help show the user that something is happening and make problems easier to identify in the future. - Notes -- There is a lot of handling of invalid FPayloads. This is because it is currently possible to add empty payloads to the trailer which is inefficient and wastes space. The trailer will be modified to reject empty payloads in a future update at which point a lot of this handling can be removed. -- This could've also been solved by not fully rehydrating a package on save by the end user, which will be added as a project setting in a future piece of work, but this approach will solve the edge case when the user does have a large amount of hydrated packages which contain payloads that are already virtualized so it was better to fix that now while we have good test cases for it. -- We still have scaling problems with large number of package being submitted that do have payloads that need to be virtualized, this will be fixed by extending IVirtualizationSystem::Push to also accept batches of payloads in future work. -- OnPrePackageSubmission could be broken up into smaller chunks to make the code easier to follow. This will be done after the batch payload submission work is done. ### VirtualizationSystem - EStorageType has been promoted to enum class. - Added a new enum FPayloadStatus to be used when querying if a payload exists in a backend storage system or not. - Add a new method ::DoPayloadsExist which allows the caller to query if one or more payloads exists in the given backend storage system. ### VirtualizationManager - Implemented ::DoPayloadsExist. First we get the results from each backend in the storage system (which return as true or false from each backend) then total how many backends found the payload in order to set the correct status. ### IVirtualizationBackend - ::DoesPayloadExist which queries the existence of a single payload has been added to the interface. Most backends already implemented this for private use and if so have had their implementation renamed to match this. - Also added ::DoPayloadsExist which takes a batch of FpayloadIdsto query. Some backends can deal with a batch of payload ids much more efficiently than one at a time, although the default implementation does call ::DoesPayloadExist for each requested payload. -- The default implementation prevents every backend from needing to implement the same for loop but does allow backends that can gain from batching to override it. ### VirtualizationSourceControlBackend - This backend does override ::DoPayloadsExist and implements it's own version as it tends to perform very poorly when not operating on larger batches. - In this case ::DoesPayloadExist calls back to ::DoPayloadsExist to check each payload rather than implement as specific version. ### PackageTrailer - The trailer can now be queries to request how many payloads of a given type it contains #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18339847 in //UE5/Release-5.0/... via CL 18339852 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18339859 by paul chipchase in ue5-release-engine-test branch]
2021-12-01 11:13:31 -05:00
}
for (int32 Index = 0; Index < Ids.Num(); ++Index)
{
if (!Ids[Index].IsZero() && Results[Index])
Submitting packages on projects with virtualization enabled is much faster when none of the payloads actually needs to be virtualized. #rb PJ.Kack #rnx #preflight 61a795773c29b3cf13cd8250 ### PackageSubmissionChecks - Under the old model submitting a large number of packages could be very slow as each package would check each payload that it owns and is currently stored locally one at a time. For the source control backend this created quite a large overhead even when all of the payloads were already virtualized. - Now we do a pass over the submitted files to find all valid packages that have package trailers with locally stored payloads, gather the payloads into a single list and then query that in one large batch. - Once we find which payloads are not in permanent storage (note that in the case where a project is using multiple permanent storage solutions, if a payload is missing in one backend it counts as not being in permanent storage) we then attempt to virtualized them. - Only after all of this is done will we create the truncated copy of each package and then append the updated trailer to each one. In theory doing it in this order this might slightly increase the change of submit failures that occur after virtualization that result in a package never being submitted and orphaned payloads being added to permanent storage, but this will always be a risk. - Added an assert to fire if we detect a trailer with some virtualized and some local payloads. This should be a supported feature but needs proper testing first before we can allow it. With out current project settings no project should actually encounter this scenario. - To make the code easier to follow we now early out of the entire check when errors are encountered. - Added logging at various stages in the process to help show the user that something is happening and make problems easier to identify in the future. - Notes -- There is a lot of handling of invalid FPayloads. This is because it is currently possible to add empty payloads to the trailer which is inefficient and wastes space. The trailer will be modified to reject empty payloads in a future update at which point a lot of this handling can be removed. -- This could've also been solved by not fully rehydrating a package on save by the end user, which will be added as a project setting in a future piece of work, but this approach will solve the edge case when the user does have a large amount of hydrated packages which contain payloads that are already virtualized so it was better to fix that now while we have good test cases for it. -- We still have scaling problems with large number of package being submitted that do have payloads that need to be virtualized, this will be fixed by extending IVirtualizationSystem::Push to also accept batches of payloads in future work. -- OnPrePackageSubmission could be broken up into smaller chunks to make the code easier to follow. This will be done after the batch payload submission work is done. ### VirtualizationSystem - EStorageType has been promoted to enum class. - Added a new enum FPayloadStatus to be used when querying if a payload exists in a backend storage system or not. - Add a new method ::DoPayloadsExist which allows the caller to query if one or more payloads exists in the given backend storage system. ### VirtualizationManager - Implemented ::DoPayloadsExist. First we get the results from each backend in the storage system (which return as true or false from each backend) then total how many backends found the payload in order to set the correct status. ### IVirtualizationBackend - ::DoesPayloadExist which queries the existence of a single payload has been added to the interface. Most backends already implemented this for private use and if so have had their implementation renamed to match this. - Also added ::DoPayloadsExist which takes a batch of FpayloadIdsto query. Some backends can deal with a batch of payload ids much more efficiently than one at a time, although the default implementation does call ::DoesPayloadExist for each requested payload. -- The default implementation prevents every backend from needing to implement the same for loop but does allow backends that can gain from batching to override it. ### VirtualizationSourceControlBackend - This backend does override ::DoPayloadsExist and implements it's own version as it tends to perform very poorly when not operating on larger batches. - In this case ::DoesPayloadExist calls back to ::DoPayloadsExist to check each payload rather than implement as specific version. ### PackageTrailer - The trailer can now be queries to request how many payloads of a given type it contains #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18339847 in //UE5/Release-5.0/... via CL 18339852 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18339859 by paul chipchase in ue5-release-engine-test branch]
2021-12-01 11:13:31 -05:00
{
HitCount[Index]++;
}
}
}
}
// Now we total up the hit count for each payload to see if it was found in none, all or some of the backends
for (int32 Index = 0; Index < Ids.Num(); ++Index)
{
if (!Ids[Index].IsZero())
Submitting packages on projects with virtualization enabled is much faster when none of the payloads actually needs to be virtualized. #rb PJ.Kack #rnx #preflight 61a795773c29b3cf13cd8250 ### PackageSubmissionChecks - Under the old model submitting a large number of packages could be very slow as each package would check each payload that it owns and is currently stored locally one at a time. For the source control backend this created quite a large overhead even when all of the payloads were already virtualized. - Now we do a pass over the submitted files to find all valid packages that have package trailers with locally stored payloads, gather the payloads into a single list and then query that in one large batch. - Once we find which payloads are not in permanent storage (note that in the case where a project is using multiple permanent storage solutions, if a payload is missing in one backend it counts as not being in permanent storage) we then attempt to virtualized them. - Only after all of this is done will we create the truncated copy of each package and then append the updated trailer to each one. In theory doing it in this order this might slightly increase the change of submit failures that occur after virtualization that result in a package never being submitted and orphaned payloads being added to permanent storage, but this will always be a risk. - Added an assert to fire if we detect a trailer with some virtualized and some local payloads. This should be a supported feature but needs proper testing first before we can allow it. With out current project settings no project should actually encounter this scenario. - To make the code easier to follow we now early out of the entire check when errors are encountered. - Added logging at various stages in the process to help show the user that something is happening and make problems easier to identify in the future. - Notes -- There is a lot of handling of invalid FPayloads. This is because it is currently possible to add empty payloads to the trailer which is inefficient and wastes space. The trailer will be modified to reject empty payloads in a future update at which point a lot of this handling can be removed. -- This could've also been solved by not fully rehydrating a package on save by the end user, which will be added as a project setting in a future piece of work, but this approach will solve the edge case when the user does have a large amount of hydrated packages which contain payloads that are already virtualized so it was better to fix that now while we have good test cases for it. -- We still have scaling problems with large number of package being submitted that do have payloads that need to be virtualized, this will be fixed by extending IVirtualizationSystem::Push to also accept batches of payloads in future work. -- OnPrePackageSubmission could be broken up into smaller chunks to make the code easier to follow. This will be done after the batch payload submission work is done. ### VirtualizationSystem - EStorageType has been promoted to enum class. - Added a new enum FPayloadStatus to be used when querying if a payload exists in a backend storage system or not. - Add a new method ::DoPayloadsExist which allows the caller to query if one or more payloads exists in the given backend storage system. ### VirtualizationManager - Implemented ::DoPayloadsExist. First we get the results from each backend in the storage system (which return as true or false from each backend) then total how many backends found the payload in order to set the correct status. ### IVirtualizationBackend - ::DoesPayloadExist which queries the existence of a single payload has been added to the interface. Most backends already implemented this for private use and if so have had their implementation renamed to match this. - Also added ::DoPayloadsExist which takes a batch of FpayloadIdsto query. Some backends can deal with a batch of payload ids much more efficiently than one at a time, although the default implementation does call ::DoesPayloadExist for each requested payload. -- The default implementation prevents every backend from needing to implement the same for loop but does allow backends that can gain from batching to override it. ### VirtualizationSourceControlBackend - This backend does override ::DoPayloadsExist and implements it's own version as it tends to perform very poorly when not operating on larger batches. - In this case ::DoesPayloadExist calls back to ::DoPayloadsExist to check each payload rather than implement as specific version. ### PackageTrailer - The trailer can now be queries to request how many payloads of a given type it contains #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18339847 in //UE5/Release-5.0/... via CL 18339852 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18339859 by paul chipchase in ue5-release-engine-test branch]
2021-12-01 11:13:31 -05:00
{
if (HitCount[Index] == 0)
{
OutStatuses[Index] = EPayloadStatus::NotFound;
Submitting packages on projects with virtualization enabled is much faster when none of the payloads actually needs to be virtualized. #rb PJ.Kack #rnx #preflight 61a795773c29b3cf13cd8250 ### PackageSubmissionChecks - Under the old model submitting a large number of packages could be very slow as each package would check each payload that it owns and is currently stored locally one at a time. For the source control backend this created quite a large overhead even when all of the payloads were already virtualized. - Now we do a pass over the submitted files to find all valid packages that have package trailers with locally stored payloads, gather the payloads into a single list and then query that in one large batch. - Once we find which payloads are not in permanent storage (note that in the case where a project is using multiple permanent storage solutions, if a payload is missing in one backend it counts as not being in permanent storage) we then attempt to virtualized them. - Only after all of this is done will we create the truncated copy of each package and then append the updated trailer to each one. In theory doing it in this order this might slightly increase the change of submit failures that occur after virtualization that result in a package never being submitted and orphaned payloads being added to permanent storage, but this will always be a risk. - Added an assert to fire if we detect a trailer with some virtualized and some local payloads. This should be a supported feature but needs proper testing first before we can allow it. With out current project settings no project should actually encounter this scenario. - To make the code easier to follow we now early out of the entire check when errors are encountered. - Added logging at various stages in the process to help show the user that something is happening and make problems easier to identify in the future. - Notes -- There is a lot of handling of invalid FPayloads. This is because it is currently possible to add empty payloads to the trailer which is inefficient and wastes space. The trailer will be modified to reject empty payloads in a future update at which point a lot of this handling can be removed. -- This could've also been solved by not fully rehydrating a package on save by the end user, which will be added as a project setting in a future piece of work, but this approach will solve the edge case when the user does have a large amount of hydrated packages which contain payloads that are already virtualized so it was better to fix that now while we have good test cases for it. -- We still have scaling problems with large number of package being submitted that do have payloads that need to be virtualized, this will be fixed by extending IVirtualizationSystem::Push to also accept batches of payloads in future work. -- OnPrePackageSubmission could be broken up into smaller chunks to make the code easier to follow. This will be done after the batch payload submission work is done. ### VirtualizationSystem - EStorageType has been promoted to enum class. - Added a new enum FPayloadStatus to be used when querying if a payload exists in a backend storage system or not. - Add a new method ::DoPayloadsExist which allows the caller to query if one or more payloads exists in the given backend storage system. ### VirtualizationManager - Implemented ::DoPayloadsExist. First we get the results from each backend in the storage system (which return as true or false from each backend) then total how many backends found the payload in order to set the correct status. ### IVirtualizationBackend - ::DoesPayloadExist which queries the existence of a single payload has been added to the interface. Most backends already implemented this for private use and if so have had their implementation renamed to match this. - Also added ::DoPayloadsExist which takes a batch of FpayloadIdsto query. Some backends can deal with a batch of payload ids much more efficiently than one at a time, although the default implementation does call ::DoesPayloadExist for each requested payload. -- The default implementation prevents every backend from needing to implement the same for loop but does allow backends that can gain from batching to override it. ### VirtualizationSourceControlBackend - This backend does override ::DoPayloadsExist and implements it's own version as it tends to perform very poorly when not operating on larger batches. - In this case ::DoesPayloadExist calls back to ::DoPayloadsExist to check each payload rather than implement as specific version. ### PackageTrailer - The trailer can now be queries to request how many payloads of a given type it contains #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18339847 in //UE5/Release-5.0/... via CL 18339852 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18339859 by paul chipchase in ue5-release-engine-test branch]
2021-12-01 11:13:31 -05:00
}
else if (HitCount[Index] == Backends.Num())
{
OutStatuses[Index] = EPayloadStatus::FoundAll;
Submitting packages on projects with virtualization enabled is much faster when none of the payloads actually needs to be virtualized. #rb PJ.Kack #rnx #preflight 61a795773c29b3cf13cd8250 ### PackageSubmissionChecks - Under the old model submitting a large number of packages could be very slow as each package would check each payload that it owns and is currently stored locally one at a time. For the source control backend this created quite a large overhead even when all of the payloads were already virtualized. - Now we do a pass over the submitted files to find all valid packages that have package trailers with locally stored payloads, gather the payloads into a single list and then query that in one large batch. - Once we find which payloads are not in permanent storage (note that in the case where a project is using multiple permanent storage solutions, if a payload is missing in one backend it counts as not being in permanent storage) we then attempt to virtualized them. - Only after all of this is done will we create the truncated copy of each package and then append the updated trailer to each one. In theory doing it in this order this might slightly increase the change of submit failures that occur after virtualization that result in a package never being submitted and orphaned payloads being added to permanent storage, but this will always be a risk. - Added an assert to fire if we detect a trailer with some virtualized and some local payloads. This should be a supported feature but needs proper testing first before we can allow it. With out current project settings no project should actually encounter this scenario. - To make the code easier to follow we now early out of the entire check when errors are encountered. - Added logging at various stages in the process to help show the user that something is happening and make problems easier to identify in the future. - Notes -- There is a lot of handling of invalid FPayloads. This is because it is currently possible to add empty payloads to the trailer which is inefficient and wastes space. The trailer will be modified to reject empty payloads in a future update at which point a lot of this handling can be removed. -- This could've also been solved by not fully rehydrating a package on save by the end user, which will be added as a project setting in a future piece of work, but this approach will solve the edge case when the user does have a large amount of hydrated packages which contain payloads that are already virtualized so it was better to fix that now while we have good test cases for it. -- We still have scaling problems with large number of package being submitted that do have payloads that need to be virtualized, this will be fixed by extending IVirtualizationSystem::Push to also accept batches of payloads in future work. -- OnPrePackageSubmission could be broken up into smaller chunks to make the code easier to follow. This will be done after the batch payload submission work is done. ### VirtualizationSystem - EStorageType has been promoted to enum class. - Added a new enum FPayloadStatus to be used when querying if a payload exists in a backend storage system or not. - Add a new method ::DoPayloadsExist which allows the caller to query if one or more payloads exists in the given backend storage system. ### VirtualizationManager - Implemented ::DoPayloadsExist. First we get the results from each backend in the storage system (which return as true or false from each backend) then total how many backends found the payload in order to set the correct status. ### IVirtualizationBackend - ::DoesPayloadExist which queries the existence of a single payload has been added to the interface. Most backends already implemented this for private use and if so have had their implementation renamed to match this. - Also added ::DoPayloadsExist which takes a batch of FpayloadIdsto query. Some backends can deal with a batch of payload ids much more efficiently than one at a time, although the default implementation does call ::DoesPayloadExist for each requested payload. -- The default implementation prevents every backend from needing to implement the same for loop but does allow backends that can gain from batching to override it. ### VirtualizationSourceControlBackend - This backend does override ::DoPayloadsExist and implements it's own version as it tends to perform very poorly when not operating on larger batches. - In this case ::DoesPayloadExist calls back to ::DoPayloadsExist to check each payload rather than implement as specific version. ### PackageTrailer - The trailer can now be queries to request how many payloads of a given type it contains #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18339847 in //UE5/Release-5.0/... via CL 18339852 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18339859 by paul chipchase in ue5-release-engine-test branch]
2021-12-01 11:13:31 -05:00
}
else
{
OutStatuses[Index] = EPayloadStatus::FoundPartial;
Submitting packages on projects with virtualization enabled is much faster when none of the payloads actually needs to be virtualized. #rb PJ.Kack #rnx #preflight 61a795773c29b3cf13cd8250 ### PackageSubmissionChecks - Under the old model submitting a large number of packages could be very slow as each package would check each payload that it owns and is currently stored locally one at a time. For the source control backend this created quite a large overhead even when all of the payloads were already virtualized. - Now we do a pass over the submitted files to find all valid packages that have package trailers with locally stored payloads, gather the payloads into a single list and then query that in one large batch. - Once we find which payloads are not in permanent storage (note that in the case where a project is using multiple permanent storage solutions, if a payload is missing in one backend it counts as not being in permanent storage) we then attempt to virtualized them. - Only after all of this is done will we create the truncated copy of each package and then append the updated trailer to each one. In theory doing it in this order this might slightly increase the change of submit failures that occur after virtualization that result in a package never being submitted and orphaned payloads being added to permanent storage, but this will always be a risk. - Added an assert to fire if we detect a trailer with some virtualized and some local payloads. This should be a supported feature but needs proper testing first before we can allow it. With out current project settings no project should actually encounter this scenario. - To make the code easier to follow we now early out of the entire check when errors are encountered. - Added logging at various stages in the process to help show the user that something is happening and make problems easier to identify in the future. - Notes -- There is a lot of handling of invalid FPayloads. This is because it is currently possible to add empty payloads to the trailer which is inefficient and wastes space. The trailer will be modified to reject empty payloads in a future update at which point a lot of this handling can be removed. -- This could've also been solved by not fully rehydrating a package on save by the end user, which will be added as a project setting in a future piece of work, but this approach will solve the edge case when the user does have a large amount of hydrated packages which contain payloads that are already virtualized so it was better to fix that now while we have good test cases for it. -- We still have scaling problems with large number of package being submitted that do have payloads that need to be virtualized, this will be fixed by extending IVirtualizationSystem::Push to also accept batches of payloads in future work. -- OnPrePackageSubmission could be broken up into smaller chunks to make the code easier to follow. This will be done after the batch payload submission work is done. ### VirtualizationSystem - EStorageType has been promoted to enum class. - Added a new enum FPayloadStatus to be used when querying if a payload exists in a backend storage system or not. - Add a new method ::DoPayloadsExist which allows the caller to query if one or more payloads exists in the given backend storage system. ### VirtualizationManager - Implemented ::DoPayloadsExist. First we get the results from each backend in the storage system (which return as true or false from each backend) then total how many backends found the payload in order to set the correct status. ### IVirtualizationBackend - ::DoesPayloadExist which queries the existence of a single payload has been added to the interface. Most backends already implemented this for private use and if so have had their implementation renamed to match this. - Also added ::DoPayloadsExist which takes a batch of FpayloadIdsto query. Some backends can deal with a batch of payload ids much more efficiently than one at a time, although the default implementation does call ::DoesPayloadExist for each requested payload. -- The default implementation prevents every backend from needing to implement the same for loop but does allow backends that can gain from batching to override it. ### VirtualizationSourceControlBackend - This backend does override ::DoPayloadsExist and implements it's own version as it tends to perform very poorly when not operating on larger batches. - In this case ::DoesPayloadExist calls back to ::DoPayloadsExist to check each payload rather than implement as specific version. ### PackageTrailer - The trailer can now be queries to request how many payloads of a given type it contains #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18339847 in //UE5/Release-5.0/... via CL 18339852 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18339859 by paul chipchase in ue5-release-engine-test branch]
2021-12-01 11:13:31 -05:00
}
}
}
return EQueryResult::Success;
Submitting packages on projects with virtualization enabled is much faster when none of the payloads actually needs to be virtualized. #rb PJ.Kack #rnx #preflight 61a795773c29b3cf13cd8250 ### PackageSubmissionChecks - Under the old model submitting a large number of packages could be very slow as each package would check each payload that it owns and is currently stored locally one at a time. For the source control backend this created quite a large overhead even when all of the payloads were already virtualized. - Now we do a pass over the submitted files to find all valid packages that have package trailers with locally stored payloads, gather the payloads into a single list and then query that in one large batch. - Once we find which payloads are not in permanent storage (note that in the case where a project is using multiple permanent storage solutions, if a payload is missing in one backend it counts as not being in permanent storage) we then attempt to virtualized them. - Only after all of this is done will we create the truncated copy of each package and then append the updated trailer to each one. In theory doing it in this order this might slightly increase the change of submit failures that occur after virtualization that result in a package never being submitted and orphaned payloads being added to permanent storage, but this will always be a risk. - Added an assert to fire if we detect a trailer with some virtualized and some local payloads. This should be a supported feature but needs proper testing first before we can allow it. With out current project settings no project should actually encounter this scenario. - To make the code easier to follow we now early out of the entire check when errors are encountered. - Added logging at various stages in the process to help show the user that something is happening and make problems easier to identify in the future. - Notes -- There is a lot of handling of invalid FPayloads. This is because it is currently possible to add empty payloads to the trailer which is inefficient and wastes space. The trailer will be modified to reject empty payloads in a future update at which point a lot of this handling can be removed. -- This could've also been solved by not fully rehydrating a package on save by the end user, which will be added as a project setting in a future piece of work, but this approach will solve the edge case when the user does have a large amount of hydrated packages which contain payloads that are already virtualized so it was better to fix that now while we have good test cases for it. -- We still have scaling problems with large number of package being submitted that do have payloads that need to be virtualized, this will be fixed by extending IVirtualizationSystem::Push to also accept batches of payloads in future work. -- OnPrePackageSubmission could be broken up into smaller chunks to make the code easier to follow. This will be done after the batch payload submission work is done. ### VirtualizationSystem - EStorageType has been promoted to enum class. - Added a new enum FPayloadStatus to be used when querying if a payload exists in a backend storage system or not. - Add a new method ::DoPayloadsExist which allows the caller to query if one or more payloads exists in the given backend storage system. ### VirtualizationManager - Implemented ::DoPayloadsExist. First we get the results from each backend in the storage system (which return as true or false from each backend) then total how many backends found the payload in order to set the correct status. ### IVirtualizationBackend - ::DoesPayloadExist which queries the existence of a single payload has been added to the interface. Most backends already implemented this for private use and if so have had their implementation renamed to match this. - Also added ::DoPayloadsExist which takes a batch of FpayloadIdsto query. Some backends can deal with a batch of payload ids much more efficiently than one at a time, although the default implementation does call ::DoesPayloadExist for each requested payload. -- The default implementation prevents every backend from needing to implement the same for loop but does allow backends that can gain from batching to override it. ### VirtualizationSourceControlBackend - This backend does override ::DoPayloadsExist and implements it's own version as it tends to perform very poorly when not operating on larger batches. - In this case ::DoesPayloadExist calls back to ::DoPayloadsExist to check each payload rather than implement as specific version. ### PackageTrailer - The trailer can now be queries to request how many payloads of a given type it contains #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18339847 in //UE5/Release-5.0/... via CL 18339852 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18339859 by paul chipchase in ue5-release-engine-test branch]
2021-12-01 11:13:31 -05:00
}
FVirtualizationResult FVirtualizationManager::TryVirtualizePackages(TConstArrayView<FString> PackagePaths, EVirtualizationOptions Options)
{
FVirtualizationResult Result;
if (IsEnabled() && IsPushingEnabled(EStorageType::Persistent))
{
const TArray<FString> SanitizedPaths = SanitizeFilePaths(PackagePaths);
UE::Virtualization::VirtualizePackages(SanitizedPaths, Options, Result);
if (Result.WasSuccessful() && !VirtualizationProcessTag.IsEmpty())
{
Result.DescriptionTags.Add(FText::FromString(VirtualizationProcessTag));
}
}
return Result;
}
FRehydrationResult FVirtualizationManager::TryRehydratePackages(TConstArrayView<FString> PackagePaths, ERehydrationOptions Options)
Add a rehydration command to the stand alone virtualization tool, making it easier to reverse the effects of asset virtualization. Unlike previous processes, this one does not require that we load the package and will just manipulate the data storaged in the package trailer. #rb Sebastian.Nordgren #rnx #jira UE-156436 #preflight 62c287f9a3568e30664eb94f ### VA Standalone Tool - We now plan to add much more functionality to the tool than just virtualizing and submitting changelists, so to make this easier I am moving the tool towards a design where it should be fairly easy to add new functionality. - Added FCommand, which is a base class for adding new functionality, simple derive from FCommand and hook it up at the appropriate locations. -- In the future it should be possible for new command types to automatically register themselves to be initiated from the command line. There should be no need to edit UnrealVirtualizationToolApp to add a new command but this will be done as an additional work item. -- At the moment FCommand comes with a number of utility methods to call that cover some common source control commands. -- The original functionality has not yet been moved to the command system and so the code is a little bit weird at the moment. Updating older code to the new system will be done as an additional work item. - FProject/FPlugin have been moved to their own code files. ### Rehydrate Command - The rehydrate command will take a number of packages, check them out of source control and then attempt to virtualize them. - At the moment the chekout logic is fairly basic, we just check out every package supplied, we don't check if the package is virtualized or not yet. This can be improved in additional work items. Ideally by the end of command the only packages that we have checked out should also be rehydrated. - At the moment the command can either take a path of a specific package, a path of a directory to find packages in, or a changelist containing packages that should be rehydrated. - A cleint spec (workspace) can optionally be provided, but if not supplied we will attempt to find a client spec for which to check out the packages. - Currently we will check out the packages to the default change list. ### Rehydrate process - Added the rehydration process in it's own code files in the virtualization module. Like the virtualization process this is exposed in a public header file and no via the Core interface which means it is very specific to our module/implementation. - The process expects that the caller will have checked out any required packages from source control. It will treat being unable to update a package file as an error. - Added PackageUtils.h/.cpp and moved some of the generic code from the virtualization process code there so that it can be shared by the rehydration process. ### Misc Moving away from the using things like FPackagePath as that requires that the correct mount points have been registered for a project and at the moment (with the flakiness of FConfig*) it seems that the best idea would be to prefer absolute file paths where possible. [CL 20982284 by paul chipchase in ue5-main branch]
2022-07-07 06:54:33 -04:00
{
FRehydrationResult Result;
Add a rehydration command to the stand alone virtualization tool, making it easier to reverse the effects of asset virtualization. Unlike previous processes, this one does not require that we load the package and will just manipulate the data storaged in the package trailer. #rb Sebastian.Nordgren #rnx #jira UE-156436 #preflight 62c287f9a3568e30664eb94f ### VA Standalone Tool - We now plan to add much more functionality to the tool than just virtualizing and submitting changelists, so to make this easier I am moving the tool towards a design where it should be fairly easy to add new functionality. - Added FCommand, which is a base class for adding new functionality, simple derive from FCommand and hook it up at the appropriate locations. -- In the future it should be possible for new command types to automatically register themselves to be initiated from the command line. There should be no need to edit UnrealVirtualizationToolApp to add a new command but this will be done as an additional work item. -- At the moment FCommand comes with a number of utility methods to call that cover some common source control commands. -- The original functionality has not yet been moved to the command system and so the code is a little bit weird at the moment. Updating older code to the new system will be done as an additional work item. - FProject/FPlugin have been moved to their own code files. ### Rehydrate Command - The rehydrate command will take a number of packages, check them out of source control and then attempt to virtualize them. - At the moment the chekout logic is fairly basic, we just check out every package supplied, we don't check if the package is virtualized or not yet. This can be improved in additional work items. Ideally by the end of command the only packages that we have checked out should also be rehydrated. - At the moment the command can either take a path of a specific package, a path of a directory to find packages in, or a changelist containing packages that should be rehydrated. - A cleint spec (workspace) can optionally be provided, but if not supplied we will attempt to find a client spec for which to check out the packages. - Currently we will check out the packages to the default change list. ### Rehydrate process - Added the rehydration process in it's own code files in the virtualization module. Like the virtualization process this is exposed in a public header file and no via the Core interface which means it is very specific to our module/implementation. - The process expects that the caller will have checked out any required packages from source control. It will treat being unable to update a package file as an error. - Added PackageUtils.h/.cpp and moved some of the generic code from the virtualization process code there so that it can be shared by the rehydration process. ### Misc Moving away from the using things like FPackagePath as that requires that the correct mount points have been registered for a project and at the moment (with the flakiness of FConfig*) it seems that the best idea would be to prefer absolute file paths where possible. [CL 20982284 by paul chipchase in ue5-main branch]
2022-07-07 06:54:33 -04:00
const TArray<FString> SanitizedPaths = SanitizeFilePaths(PackagePaths);
UE::Virtualization::RehydratePackages(SanitizedPaths, Options, Result);
return Result;
}
ERehydrationResult FVirtualizationManager::TryRehydratePackages(TConstArrayView<FString> PackagePaths, uint64 PaddingAlignment, TArray<FText>& OutErrors, TArray<FSharedBuffer>& OutPackages, TArray<FRehydrationInfo>* OutInfo)
{
OutErrors.Reset();
UE::Virtualization::RehydratePackages(PackagePaths, PaddingAlignment, OutErrors, OutPackages, OutInfo);
Add a rehydration command to the stand alone virtualization tool, making it easier to reverse the effects of asset virtualization. Unlike previous processes, this one does not require that we load the package and will just manipulate the data storaged in the package trailer. #rb Sebastian.Nordgren #rnx #jira UE-156436 #preflight 62c287f9a3568e30664eb94f ### VA Standalone Tool - We now plan to add much more functionality to the tool than just virtualizing and submitting changelists, so to make this easier I am moving the tool towards a design where it should be fairly easy to add new functionality. - Added FCommand, which is a base class for adding new functionality, simple derive from FCommand and hook it up at the appropriate locations. -- In the future it should be possible for new command types to automatically register themselves to be initiated from the command line. There should be no need to edit UnrealVirtualizationToolApp to add a new command but this will be done as an additional work item. -- At the moment FCommand comes with a number of utility methods to call that cover some common source control commands. -- The original functionality has not yet been moved to the command system and so the code is a little bit weird at the moment. Updating older code to the new system will be done as an additional work item. - FProject/FPlugin have been moved to their own code files. ### Rehydrate Command - The rehydrate command will take a number of packages, check them out of source control and then attempt to virtualize them. - At the moment the chekout logic is fairly basic, we just check out every package supplied, we don't check if the package is virtualized or not yet. This can be improved in additional work items. Ideally by the end of command the only packages that we have checked out should also be rehydrated. - At the moment the command can either take a path of a specific package, a path of a directory to find packages in, or a changelist containing packages that should be rehydrated. - A cleint spec (workspace) can optionally be provided, but if not supplied we will attempt to find a client spec for which to check out the packages. - Currently we will check out the packages to the default change list. ### Rehydrate process - Added the rehydration process in it's own code files in the virtualization module. Like the virtualization process this is exposed in a public header file and no via the Core interface which means it is very specific to our module/implementation. - The process expects that the caller will have checked out any required packages from source control. It will treat being unable to update a package file as an error. - Added PackageUtils.h/.cpp and moved some of the generic code from the virtualization process code there so that it can be shared by the rehydration process. ### Misc Moving away from the using things like FPackagePath as that requires that the correct mount points have been registered for a project and at the moment (with the flakiness of FConfig*) it seems that the best idea would be to prefer absolute file paths where possible. [CL 20982284 by paul chipchase in ue5-main branch]
2022-07-07 06:54:33 -04:00
Add an ini file option which when set to true allows package submissions to source control to go ahead even if the virtualization process failed. #rb none #jira UE-159596 #rnx #preflight 62d94160110da0f944afdd32 ### Problem - When rolling our virtualization to projects we have run into a number of set up problems which has caused users to fail to submit packages from the editor as when the virtualization failed we prevented the overall submit from going through. - Although we will eventually work through all of these problems and add better fault tolerance for now it is annoying for the content team so we need an easy way for a project to allow package submits to be completed even if the virtualization process part of the submit failed. - Worth noting that the virtualization process failing should never affect the state of the package files, the only downside is that the packages may not be virtualized. ### Fix - The virtualization/rehydration of packages now return an enum instead of a bool although at the moment we are only returning Success and Failed, but it will allow us to expand in the future - Combined the code calling the virtualization process from both the source control window and the source control changelist window into a single utility function. -- Now the two windows only diverge on how they report failure to the user. - This new utility function now checks to see if the virtualization manager suggests if failing the virtualization process should block any package submission to source control or not. - I am not happy with this solution, but I haven't come up with anything that feels right, this solution will at least work. [CL 21199597 by paul chipchase in ue5-main branch]
2022-07-21 08:31:47 -04:00
return OutErrors.IsEmpty() ? ERehydrationResult::Success : ERehydrationResult::Failed;
Add a rehydration command to the stand alone virtualization tool, making it easier to reverse the effects of asset virtualization. Unlike previous processes, this one does not require that we load the package and will just manipulate the data storaged in the package trailer. #rb Sebastian.Nordgren #rnx #jira UE-156436 #preflight 62c287f9a3568e30664eb94f ### VA Standalone Tool - We now plan to add much more functionality to the tool than just virtualizing and submitting changelists, so to make this easier I am moving the tool towards a design where it should be fairly easy to add new functionality. - Added FCommand, which is a base class for adding new functionality, simple derive from FCommand and hook it up at the appropriate locations. -- In the future it should be possible for new command types to automatically register themselves to be initiated from the command line. There should be no need to edit UnrealVirtualizationToolApp to add a new command but this will be done as an additional work item. -- At the moment FCommand comes with a number of utility methods to call that cover some common source control commands. -- The original functionality has not yet been moved to the command system and so the code is a little bit weird at the moment. Updating older code to the new system will be done as an additional work item. - FProject/FPlugin have been moved to their own code files. ### Rehydrate Command - The rehydrate command will take a number of packages, check them out of source control and then attempt to virtualize them. - At the moment the chekout logic is fairly basic, we just check out every package supplied, we don't check if the package is virtualized or not yet. This can be improved in additional work items. Ideally by the end of command the only packages that we have checked out should also be rehydrated. - At the moment the command can either take a path of a specific package, a path of a directory to find packages in, or a changelist containing packages that should be rehydrated. - A cleint spec (workspace) can optionally be provided, but if not supplied we will attempt to find a client spec for which to check out the packages. - Currently we will check out the packages to the default change list. ### Rehydrate process - Added the rehydration process in it's own code files in the virtualization module. Like the virtualization process this is exposed in a public header file and no via the Core interface which means it is very specific to our module/implementation. - The process expects that the caller will have checked out any required packages from source control. It will treat being unable to update a package file as an error. - Added PackageUtils.h/.cpp and moved some of the generic code from the virtualization process code there so that it can be shared by the rehydration process. ### Misc Moving away from the using things like FPackagePath as that requires that the correct mount points have been registered for a project and at the moment (with the flakiness of FConfig*) it seems that the best idea would be to prefer absolute file paths where possible. [CL 20982284 by paul chipchase in ue5-main branch]
2022-07-07 06:54:33 -04:00
}
void FVirtualizationManager::DumpStats() const
{
#if ENABLE_COOK_STATS
Profiling::LogStats();
#endif // ENABLE_COOK_STATS
}
FPayloadActivityInfo FVirtualizationManager::GetAccumualtedPayloadActivityInfo() const
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
{
FPayloadActivityInfo Info;
#if ENABLE_COOK_STATS
for (const auto& Iterator : Profiling::CacheStats)
{
Info.Cache.PayloadCount += Iterator.Value.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Counter);
Info.Cache.TotalBytes += Iterator.Value.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Bytes);
Info.Cache.CyclesSpent += Iterator.Value.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Cycles);
}
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
for (const auto& Iterator : Profiling::PushStats)
{
Info.Push.PayloadCount += Iterator.Value.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Counter);
Info.Push.TotalBytes += Iterator.Value.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Bytes);
Info.Push.CyclesSpent += Iterator.Value.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Cycles);
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
}
for (const auto& Iterator : Profiling::PullStats)
{
Info.Pull.PayloadCount += Iterator.Value.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Counter);
Info.Pull.TotalBytes += Iterator.Value.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Bytes);
Info.Pull.CyclesSpent += Iterator.Value.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Cycles);
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
}
#endif // ENABLE_COOK_STATS
return Info;
}
void FVirtualizationManager::GetPayloadActivityInfo( GetPayloadActivityInfoFuncRef GetPayloadFunc ) const
{
FPayloadActivityInfo Info;
#if ENABLE_COOK_STATS
for (const auto& Backend : AllBackends)
{
const FCookStats::CallStats& CacheStats = Profiling::GetCacheStats(*Backend);
Info.Cache.PayloadCount = CacheStats.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Counter);
Info.Cache.TotalBytes = CacheStats.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Bytes);
Info.Cache.CyclesSpent = CacheStats.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Cycles);
const FCookStats::CallStats& PushStats = Profiling::GetPushStats(*Backend);
Info.Push.PayloadCount = PushStats.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Counter);
Info.Push.TotalBytes = PushStats.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Bytes);
Info.Push.CyclesSpent = PushStats.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Cycles);
const FCookStats::CallStats& PullStats = Profiling::GetPullStats(*Backend);
Info.Pull.PayloadCount = PullStats.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Counter);
Info.Pull.TotalBytes = PullStats.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Bytes);
Info.Pull.CyclesSpent = PullStats.GetAccumulatedValueAnyThread(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Cycles);
GetPayloadFunc(Backend->GetDebugName(), Backend->GetConfigName(), Info);
}
#endif // ENABLE_COOK_STATS
}
void FVirtualizationManager::ApplySettingsFromConfigFiles(const FConfigFile& ConfigFile)
{
UE_LOG(LogVirtualization, Display, TEXT("Loading virtualization manager settings from config files..."));
const TCHAR* LegacyConfigSection = TEXT("Core.ContentVirtualization");
const TCHAR* ConfigSection = TEXT("Core.VirtualizationModule");
// Note that many options are doubled up as we are moving the options for this module from "Core.ContentVirtualization"
// to it's own specific "Core.VirtualizationModule" section. This duplication can be removed before we ship 5.1
// The backend graph is the most important value and so should come first for logging purposes
{
if (!ConfigFile.GetString(LegacyConfigSection, TEXT("BackendGraph"), BackendGraphName))
{
ConfigFile.GetString(ConfigSection, TEXT("BackendGraph"), BackendGraphName);
}
UE_LOG(LogVirtualization, Display, TEXT("\tBackendGraphName : %s"), *BackendGraphName);
}
{
// This value was moved from Core.ContentVirtualization to Core.VirtualizationModule then renamed from
// 'EnablePushToBackend' to 'EnablePayloadVirtualization' so there are a few paths we need to cover here.
// This can also be cleaned up for 5.1 shipping.
if (ConfigFile.GetBool(LegacyConfigSection, TEXT("EnablePushToBackend"), bAllowPackageVirtualization))
{
UE_LOG(LogVirtualization, Warning, TEXT("\tFound legacy ini file setting [Core.ContentVirtualization].EnablePushToBackend, rename to [Core.VirtualizationModule].EnablePayloadVirtualization"));
}
else if (ConfigFile.GetBool(ConfigSection, TEXT("EnablePushToBackend"), bAllowPackageVirtualization))
{
UE_LOG(LogVirtualization, Warning, TEXT("\tFound legacy ini file setting [Core.VirtualizationModule].EnablePushToBackend, rename to [Core.VirtualizationModule].EnablePayloadVirtualization"));
}
else
{
ConfigFile.GetBool(ConfigSection, TEXT("EnablePayloadVirtualization"), bAllowPackageVirtualization);
}
UE_LOG(LogVirtualization, Display, TEXT("\tEnablePayloadVirtualization : %s"), bAllowPackageVirtualization ? TEXT("true") : TEXT("false"));
}
{
bool bCacheOnPull = true;
if (ConfigFile.GetBool(LegacyConfigSection, TEXT("EnableCacheAfterPull"), bCacheOnPull) ||
ConfigFile.GetBool(ConfigSection, TEXT("EnableCacheAfterPull"), bCacheOnPull))
{
UE_LOG(LogVirtualization, Warning, TEXT("\tEnableCacheAfterPull is deprecated, replace with 'EnableCacheOnPull=True|False'"));
}
else
{
ConfigFile.GetBool(ConfigSection, TEXT("EnableCacheOnPull"), bCacheOnPull);
}
if (!bCacheOnPull)
{
EnumRemoveFlags(CachingPolicy, ECachingPolicy::CacheOnPull);
}
UE_LOG(LogVirtualization, Display, TEXT("\tEnableCacheOnPull : %s"), EnumHasAllFlags(CachingPolicy, ECachingPolicy::CacheOnPull) ? TEXT("true") : TEXT("false"));
}
{
bool bCacheOnPush = true;
ConfigFile.GetBool(ConfigSection, TEXT("EnableCacheOnPush"), bCacheOnPush);
if (!bCacheOnPush)
{
EnumRemoveFlags(CachingPolicy, ECachingPolicy::CacheOnPush);
}
UE_LOG(LogVirtualization, Display, TEXT("\tEnableCacheOnPush : %s"), EnumHasAllFlags(CachingPolicy, ECachingPolicy::CacheOnPush) ? TEXT("true") : TEXT("false"));
}
{
if (!ConfigFile.GetInt64(LegacyConfigSection, TEXT("MinPayloadLength"), MinPayloadLength))
{
ConfigFile.GetInt64(ConfigSection, TEXT("MinPayloadLength"), MinPayloadLength);
}
UE_LOG(LogVirtualization, Display, TEXT("\tMinPayloadLength : %" INT64_FMT), MinPayloadLength);
}
{
ConfigFile.GetString(ConfigSection, TEXT("VirtualizationProcessTag"), VirtualizationProcessTag);
UE_LOG(LogVirtualization, Display, TEXT("\tVirtualizationProcessTag : %s"), *VirtualizationProcessTag);
}
{
FString FilterModeString;
if (ConfigFile.GetString(LegacyConfigSection, TEXT("FilterMode"), FilterModeString) ||
ConfigFile.GetString(ConfigSection, TEXT("FilterMode"), FilterModeString))
{
if (!LexTryParseString(FilteringMode, FilterModeString))
{
UE_LOG(LogVirtualization, Error, TEXT("[Core.VirtualizationModule].FilterMode was an invalid value! Allowed: 'OptIn'|'OptOut' Found '%s'"), *FilterModeString);
}
}
UE_LOG(LogVirtualization, Display, TEXT("\tFilterMode : %s"), LexToString(FilteringMode));
}
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
{
ConfigFile.GetBool(ConfigSection, TEXT("FilterMapContent"), bFilterMapContent);
UE_LOG(LogVirtualization, Display, TEXT("\tFilterMapContent : %s"), bFilterMapContent ? TEXT("true") : TEXT("false"));
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
}
TArray<FString> DisabledAssetTypesFromIni;
if (ConfigFile.GetArray(LegacyConfigSection, TEXT("DisabledAsset"), DisabledAssetTypesFromIni) > 0 ||
ConfigFile.GetArray(ConfigSection, TEXT("DisabledAsset"), DisabledAssetTypesFromIni) > 0)
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
{
UE_LOG(LogVirtualization, Display, TEXT("\tVirtualization is disabled for payloads of the following assets:"));
DisabledAssetTypes.Reserve(DisabledAssetTypesFromIni.Num());
for(const FString& AssetType : DisabledAssetTypesFromIni)
{
UE_LOG(LogVirtualization, Display, TEXT("\t\t%s"), *AssetType);
DisabledAssetTypes.Add(FName(AssetType));
}
}
{
ConfigFile.GetBool(ConfigSection, TEXT("AllowSubmitIfVirtualizationFailed"), bAllowSubmitIfVirtualizationFailed);
UE_LOG(LogVirtualization, Display, TEXT("\tAllowSubmitIfVirtualizationFailed : %s"), bAllowSubmitIfVirtualizationFailed ? TEXT("true") : TEXT("false"));
}
#if UE_VIRTUALIZATION_CONNECTION_LAZY_INIT == 0
ConfigFile.GetBool(ConfigSection, TEXT("LazyInitConnections"), bLazyInitConnections);
UE_LOG(LogVirtualization, Display, TEXT("\tLazyInitConnections : %s"), bLazyInitConnections ? TEXT("true") : TEXT("false"));
#else
bLazyInitConnections = true;
UE_LOG(LogVirtualization, Display, TEXT("\tLazyInitConnections : true (set by code)"));
#endif //UE_VIRTUALIZATION_CONNECTION_LAZY_INIT
{
ConfigFile.GetBool(ConfigSection, TEXT("UseLegacyErrorHandling"), bUseLegacyErrorHandling);
UE_LOG(LogVirtualization, Display, TEXT("\tUseLegacyErrorHandling : %s"), bUseLegacyErrorHandling ? TEXT("true") : TEXT("false"));
}
{
ConfigFile.GetString(ConfigSection, TEXT("PullErrorAdditionalMsg"), PullErrorAdditionalMsg);
// This value is not echoed to the log file, as seeing an error string there might confuse users
}
{
ConfigFile.GetBool(ConfigSection, TEXT("ForceCachingOnPull"), bForceCachingOnPull);
UE_LOG(LogVirtualization, Display, TEXT("\tForceCachingOnPull : %s"), bForceCachingOnPull ? TEXT("true") : TEXT("false"));
}
// Deprecated
{
bool bDummyValue = true;
if (ConfigFile.GetBool(LegacyConfigSection, TEXT("FilterEngineContent"), bDummyValue) ||
ConfigFile.GetBool(ConfigSection, TEXT("FilterEngineContent"), bDummyValue))
{
UE_LOG(LogVirtualization, Warning, TEXT("\tFilterEngineContent is now deprecated (engine content is never virtualized)"));
}
if (ConfigFile.GetBool(LegacyConfigSection, TEXT("FilterEnginePluginContent"), bDummyValue) ||
ConfigFile.GetBool(ConfigSection, TEXT("FilterEnginePluginContent"), bDummyValue))
{
UE_LOG(LogVirtualization, Warning, TEXT("\tFilterEnginePluginContent is now deprecated (engine content is never virtualized)"));
}
It is now possible to disable virtualization for all payloads owned by a specific asset type by adding the name of the asset to [Core.ContentVirtualization]DisabledAsset string array in the engine ini file. #rb Per.Larsson #rnx #jira UE-151377 #preflight 628364050039ea57a52d6989 ### Virtualization - [Core.ContentVirtualization] in the engine ini file now supports an array called 'DisabledAsset' which can be used to name asset types that should not virtualize their payloads. -- By default (in BaseEngine.ini) we have disabled the StaticMesh asset as we know it will crash if a payload is missing and the SoundWave asset as it still is pending testing. - This new way to disable virtualization is data driven. The older hard coded method has not been removed but will likely be reworked in a future submit. - Now when an editor bulkdata is adding it's payload to the package trailer builder during package save it will poll the virtualization system with a call to the new method ::IsDisabledForObject by passing in it's owner. -- If the owner is valid and was present in the 'DisabledAsset' array then the method will return true and the EPayloadFlags::DisableVirtualization flag will be applied. ### Package Trailer - The pre-existing functionality of enum EPayloadFilter has been moved to a new enum EPayloadStorageType as will only filter payloads based on their storage type. - EPayloadFilter has been modified to filter payloads based on functionality although at the moment the only thing it can filter for is to return payloads that can be virtualized, it is left for future expansion. - EPayloadFlags has been reduced to a uint16 with the remaining 2bytes being turned into a new member EPayloadFilterReason. - This new member allows us to record the exact reason why a payload is excluded from virtualization. If it is zero then the payload can virtualize, otherwise it will contain one or more reasons as to why it is being excluded. For this reason the enum is a bitfield. - Added overloads of ::GetPayloads and ::GetNumPayloads that take EPayloadFilter rather than a EPayloadStorageType - Added wrappers around all AccessMode types for FLookupTableEntry. - FPackageTrailerBuilder has been extended to take a EPayloadFilterReason so that the caller can already provide a reason why the payload cannot be virtualized. -- As a future peace of work this will probably be changed and we will ask the caller to pass in the owner UObject pointer instead and then we will process the filtering when building the package trailer to a) keep all of the filtering code in one place b) keep the filtering consistent ### PackageSubmissionChecks - The virtualization process in will now request the payloads that can be virtualized from the package trailer, which respects the new payload flag, rather than requesting all locally stored payloads. ### UObjects - There is no need for the SoundWave or MeshDescription classes to opt out of virtualization on construction. This will be done when the package is saved and is now data driven rather than being hardcoded. ### DumpPackagePayloadInfo - The command has been updated to also display the filter reasons applied to each payload [CL 20240971 by paul chipchase in ue5-main branch]
2022-05-17 07:54:28 -04:00
}
// Check for any legacy settings and print them out (easier to do this in one block rather than one and time)
{
Add a number of ways for the VA system to be changed to lazy initialize on first use. #rb Per.Larsson #jira UE-161296 #rnx #preflight 62fe3ce73d3fb466b229bcc0 - There are some usecases that require the VA system to initialize the first time it is accessed (usually the first time we attempt to pull a virtualized payload) rather than be initialized in the program start up. This change provides three different methods to achieve this: -- Setting the define 'UE_VIRTUALIZATION_SYSTEM_LAZY_INIT' to 1 in a programs .target.cs -- Setting [Core.ContentVirtualization]LazyInit=true in the Engine ini file -- Running with the commandline option -VA-LazyInit - If we detect that the source control backend is being initialized on a background thread we do not try to run the FConnect operation. The backend will still work but this does reduce the potential error checking on initialization. This is done because the FConnect operation currently only works on the main thread and to change this would be a bigger work item than we can schedule at the moment. - UE::Virtualization::Initialize functions now take a EInitializationFlags enum as a parameter. This enum allows the call to ignore all lazy init settings and force the initialization immediately. This is useful for programs like the Virtualization standalone tool which just needs to start the system when needed. -- The call to ::Initialize in LaunchEngineLoop passes in None and does not ignore lazy initialization. -- Calls to ::Initialize in the UnrealVirtualizationTool however all use EInitializationFlags::ForceInitialize and ignore lazy initialization settings. - Fixed an odd bug in UE::Virtualization::Initialize where the error path (if the config file cannot be found) was using a different start up code path. - Add asserts when assigning to GVirtualizationSystem to make sure that it is null. This is not 100% safe but should catch some potential threading issues, if any. - Add an assert after lazy initialization (IVirtualizationSystem::Get) to make sure that GVirtualizationSystem was assigned a valid object. - Improve how we check for legacy values in [Core.ContentVirtualization]. We now support multiple allowed values. - Added a way to poll if a VA system has been initialize yet or not, this allows us to avoid initializing a VA system if one has not yet been created and we try to: -- Dump VA profiling stats after cooking -- Send VA stats to studio analytics - Note that currently using lazy init loading will probably cause the VA statistics panel not to work, this will be fixed in future work where we will allow the panel to register for a callback when the system is initialized. [CL 21467510 by paul chipchase in ue5-main branch]
2022-08-19 19:15:42 -04:00
// Entries that are allows to be in [Core.ContentVirtualization
static const TArray<FString> AllowedEntries = { TEXT("SystemName") , TEXT("LazyInit") };
Add a number of ways for the VA system to be changed to lazy initialize on first use. #rb Per.Larsson #jira UE-161296 #rnx #preflight 62fe3ce73d3fb466b229bcc0 - There are some usecases that require the VA system to initialize the first time it is accessed (usually the first time we attempt to pull a virtualized payload) rather than be initialized in the program start up. This change provides three different methods to achieve this: -- Setting the define 'UE_VIRTUALIZATION_SYSTEM_LAZY_INIT' to 1 in a programs .target.cs -- Setting [Core.ContentVirtualization]LazyInit=true in the Engine ini file -- Running with the commandline option -VA-LazyInit - If we detect that the source control backend is being initialized on a background thread we do not try to run the FConnect operation. The backend will still work but this does reduce the potential error checking on initialization. This is done because the FConnect operation currently only works on the main thread and to change this would be a bigger work item than we can schedule at the moment. - UE::Virtualization::Initialize functions now take a EInitializationFlags enum as a parameter. This enum allows the call to ignore all lazy init settings and force the initialization immediately. This is useful for programs like the Virtualization standalone tool which just needs to start the system when needed. -- The call to ::Initialize in LaunchEngineLoop passes in None and does not ignore lazy initialization. -- Calls to ::Initialize in the UnrealVirtualizationTool however all use EInitializationFlags::ForceInitialize and ignore lazy initialization settings. - Fixed an odd bug in UE::Virtualization::Initialize where the error path (if the config file cannot be found) was using a different start up code path. - Add asserts when assigning to GVirtualizationSystem to make sure that it is null. This is not 100% safe but should catch some potential threading issues, if any. - Add an assert after lazy initialization (IVirtualizationSystem::Get) to make sure that GVirtualizationSystem was assigned a valid object. - Improve how we check for legacy values in [Core.ContentVirtualization]. We now support multiple allowed values. - Added a way to poll if a VA system has been initialize yet or not, this allows us to avoid initializing a VA system if one has not yet been created and we try to: -- Dump VA profiling stats after cooking -- Send VA stats to studio analytics - Note that currently using lazy init loading will probably cause the VA statistics panel not to work, this will be fixed in future work where we will allow the panel to register for a callback when the system is initialized. [CL 21467510 by paul chipchase in ue5-main branch]
2022-08-19 19:15:42 -04:00
TArray<FString> LegacyEntries;
if (const FConfigSection* LegacySection = ConfigFile.Find(LegacyConfigSection))
{
Add a number of ways for the VA system to be changed to lazy initialize on first use. #rb Per.Larsson #jira UE-161296 #rnx #preflight 62fe3ce73d3fb466b229bcc0 - There are some usecases that require the VA system to initialize the first time it is accessed (usually the first time we attempt to pull a virtualized payload) rather than be initialized in the program start up. This change provides three different methods to achieve this: -- Setting the define 'UE_VIRTUALIZATION_SYSTEM_LAZY_INIT' to 1 in a programs .target.cs -- Setting [Core.ContentVirtualization]LazyInit=true in the Engine ini file -- Running with the commandline option -VA-LazyInit - If we detect that the source control backend is being initialized on a background thread we do not try to run the FConnect operation. The backend will still work but this does reduce the potential error checking on initialization. This is done because the FConnect operation currently only works on the main thread and to change this would be a bigger work item than we can schedule at the moment. - UE::Virtualization::Initialize functions now take a EInitializationFlags enum as a parameter. This enum allows the call to ignore all lazy init settings and force the initialization immediately. This is useful for programs like the Virtualization standalone tool which just needs to start the system when needed. -- The call to ::Initialize in LaunchEngineLoop passes in None and does not ignore lazy initialization. -- Calls to ::Initialize in the UnrealVirtualizationTool however all use EInitializationFlags::ForceInitialize and ignore lazy initialization settings. - Fixed an odd bug in UE::Virtualization::Initialize where the error path (if the config file cannot be found) was using a different start up code path. - Add asserts when assigning to GVirtualizationSystem to make sure that it is null. This is not 100% safe but should catch some potential threading issues, if any. - Add an assert after lazy initialization (IVirtualizationSystem::Get) to make sure that GVirtualizationSystem was assigned a valid object. - Improve how we check for legacy values in [Core.ContentVirtualization]. We now support multiple allowed values. - Added a way to poll if a VA system has been initialize yet or not, this allows us to avoid initializing a VA system if one has not yet been created and we try to: -- Dump VA profiling stats after cooking -- Send VA stats to studio analytics - Note that currently using lazy init loading will probably cause the VA statistics panel not to work, this will be fixed in future work where we will allow the panel to register for a callback when the system is initialized. [CL 21467510 by paul chipchase in ue5-main branch]
2022-08-19 19:15:42 -04:00
for (const TPair<FName, FConfigValue>& It : *LegacySection)
{
Add a number of ways for the VA system to be changed to lazy initialize on first use. #rb Per.Larsson #jira UE-161296 #rnx #preflight 62fe3ce73d3fb466b229bcc0 - There are some usecases that require the VA system to initialize the first time it is accessed (usually the first time we attempt to pull a virtualized payload) rather than be initialized in the program start up. This change provides three different methods to achieve this: -- Setting the define 'UE_VIRTUALIZATION_SYSTEM_LAZY_INIT' to 1 in a programs .target.cs -- Setting [Core.ContentVirtualization]LazyInit=true in the Engine ini file -- Running with the commandline option -VA-LazyInit - If we detect that the source control backend is being initialized on a background thread we do not try to run the FConnect operation. The backend will still work but this does reduce the potential error checking on initialization. This is done because the FConnect operation currently only works on the main thread and to change this would be a bigger work item than we can schedule at the moment. - UE::Virtualization::Initialize functions now take a EInitializationFlags enum as a parameter. This enum allows the call to ignore all lazy init settings and force the initialization immediately. This is useful for programs like the Virtualization standalone tool which just needs to start the system when needed. -- The call to ::Initialize in LaunchEngineLoop passes in None and does not ignore lazy initialization. -- Calls to ::Initialize in the UnrealVirtualizationTool however all use EInitializationFlags::ForceInitialize and ignore lazy initialization settings. - Fixed an odd bug in UE::Virtualization::Initialize where the error path (if the config file cannot be found) was using a different start up code path. - Add asserts when assigning to GVirtualizationSystem to make sure that it is null. This is not 100% safe but should catch some potential threading issues, if any. - Add an assert after lazy initialization (IVirtualizationSystem::Get) to make sure that GVirtualizationSystem was assigned a valid object. - Improve how we check for legacy values in [Core.ContentVirtualization]. We now support multiple allowed values. - Added a way to poll if a VA system has been initialize yet or not, this allows us to avoid initializing a VA system if one has not yet been created and we try to: -- Dump VA profiling stats after cooking -- Send VA stats to studio analytics - Note that currently using lazy init loading will probably cause the VA statistics panel not to work, this will be fixed in future work where we will allow the panel to register for a callback when the system is initialized. [CL 21467510 by paul chipchase in ue5-main branch]
2022-08-19 19:15:42 -04:00
FString Name = It.Key.ToString();
if (!AllowedEntries.Contains(Name))
{
Add a number of ways for the VA system to be changed to lazy initialize on first use. #rb Per.Larsson #jira UE-161296 #rnx #preflight 62fe3ce73d3fb466b229bcc0 - There are some usecases that require the VA system to initialize the first time it is accessed (usually the first time we attempt to pull a virtualized payload) rather than be initialized in the program start up. This change provides three different methods to achieve this: -- Setting the define 'UE_VIRTUALIZATION_SYSTEM_LAZY_INIT' to 1 in a programs .target.cs -- Setting [Core.ContentVirtualization]LazyInit=true in the Engine ini file -- Running with the commandline option -VA-LazyInit - If we detect that the source control backend is being initialized on a background thread we do not try to run the FConnect operation. The backend will still work but this does reduce the potential error checking on initialization. This is done because the FConnect operation currently only works on the main thread and to change this would be a bigger work item than we can schedule at the moment. - UE::Virtualization::Initialize functions now take a EInitializationFlags enum as a parameter. This enum allows the call to ignore all lazy init settings and force the initialization immediately. This is useful for programs like the Virtualization standalone tool which just needs to start the system when needed. -- The call to ::Initialize in LaunchEngineLoop passes in None and does not ignore lazy initialization. -- Calls to ::Initialize in the UnrealVirtualizationTool however all use EInitializationFlags::ForceInitialize and ignore lazy initialization settings. - Fixed an odd bug in UE::Virtualization::Initialize where the error path (if the config file cannot be found) was using a different start up code path. - Add asserts when assigning to GVirtualizationSystem to make sure that it is null. This is not 100% safe but should catch some potential threading issues, if any. - Add an assert after lazy initialization (IVirtualizationSystem::Get) to make sure that GVirtualizationSystem was assigned a valid object. - Improve how we check for legacy values in [Core.ContentVirtualization]. We now support multiple allowed values. - Added a way to poll if a VA system has been initialize yet or not, this allows us to avoid initializing a VA system if one has not yet been created and we try to: -- Dump VA profiling stats after cooking -- Send VA stats to studio analytics - Note that currently using lazy init loading will probably cause the VA statistics panel not to work, this will be fixed in future work where we will allow the panel to register for a callback when the system is initialized. [CL 21467510 by paul chipchase in ue5-main branch]
2022-08-19 19:15:42 -04:00
LegacyEntries.Add(MoveTemp(Name));
}
}
}
Add a number of ways for the VA system to be changed to lazy initialize on first use. #rb Per.Larsson #jira UE-161296 #rnx #preflight 62fe3ce73d3fb466b229bcc0 - There are some usecases that require the VA system to initialize the first time it is accessed (usually the first time we attempt to pull a virtualized payload) rather than be initialized in the program start up. This change provides three different methods to achieve this: -- Setting the define 'UE_VIRTUALIZATION_SYSTEM_LAZY_INIT' to 1 in a programs .target.cs -- Setting [Core.ContentVirtualization]LazyInit=true in the Engine ini file -- Running with the commandline option -VA-LazyInit - If we detect that the source control backend is being initialized on a background thread we do not try to run the FConnect operation. The backend will still work but this does reduce the potential error checking on initialization. This is done because the FConnect operation currently only works on the main thread and to change this would be a bigger work item than we can schedule at the moment. - UE::Virtualization::Initialize functions now take a EInitializationFlags enum as a parameter. This enum allows the call to ignore all lazy init settings and force the initialization immediately. This is useful for programs like the Virtualization standalone tool which just needs to start the system when needed. -- The call to ::Initialize in LaunchEngineLoop passes in None and does not ignore lazy initialization. -- Calls to ::Initialize in the UnrealVirtualizationTool however all use EInitializationFlags::ForceInitialize and ignore lazy initialization settings. - Fixed an odd bug in UE::Virtualization::Initialize where the error path (if the config file cannot be found) was using a different start up code path. - Add asserts when assigning to GVirtualizationSystem to make sure that it is null. This is not 100% safe but should catch some potential threading issues, if any. - Add an assert after lazy initialization (IVirtualizationSystem::Get) to make sure that GVirtualizationSystem was assigned a valid object. - Improve how we check for legacy values in [Core.ContentVirtualization]. We now support multiple allowed values. - Added a way to poll if a VA system has been initialize yet or not, this allows us to avoid initializing a VA system if one has not yet been created and we try to: -- Dump VA profiling stats after cooking -- Send VA stats to studio analytics - Note that currently using lazy init loading will probably cause the VA statistics panel not to work, this will be fixed in future work where we will allow the panel to register for a callback when the system is initialized. [CL 21467510 by paul chipchase in ue5-main branch]
2022-08-19 19:15:42 -04:00
if (!LegacyEntries.IsEmpty())
{
UE_LOG(LogVirtualization, Warning, TEXT("\tFound %d legacy ini file settings under [Core.ContentVirtualization] that should be moved to [Core.VirtualizationModule]"), LegacyEntries.Num());
for (const FString& LegacyEntry : LegacyEntries)
{
UE_LOG(LogVirtualization, Warning, TEXT("\t\t%s"), *LegacyEntry);
}
}
}
}
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
void FVirtualizationManager::ApplySettingsFromFromCmdline()
{
if (!bLazyInitConnections && IsCmdLineParamSet(TEXT("VALazyInitConnections"), TEXT("VA-LazyInitConnections")))
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
{
bLazyInitConnections = true;
UE_LOG(LogVirtualization, Display, TEXT("Cmdline has set the virtualization system backends to lazy init their connections"));
}
if (bAllowPackageVirtualization && IsCmdLineParamSet(TEXT("VASkipPkgVirtualization"), TEXT("VA-SkipPkgVirtualization")))
{
bAllowPackageVirtualization = false;
UE_LOG(LogVirtualization, Warning, TEXT("The virtualization process has been disabled via the command line"));
}
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
}
void FVirtualizationManager::ApplySettingsFromCVar()
{
if (!bLazyInitConnections && CVarLazyInitConnections.GetValueOnAnyThread())
{
bLazyInitConnections = true;
UE_LOG(LogVirtualization, Display, TEXT("CVar has set the virtualization system backends to lazy init their connections"));
}
}
void FVirtualizationManager::ApplyDebugSettingsFromFromCmdline()
{
if (IsCmdLineParamSet(TEXT("VASingleThreaded"), TEXT("VA-SingleThreaded")))
{
DebugValues.bSingleThreaded = true;
UE_LOG(LogVirtualization, Warning, TEXT("Cmdline has set the virtualization system to run single threaded"));
}
if (IsCmdLineParamSet(TEXT("VAValidatePushes"), TEXT("VA-ValidatePushes")))
{
DebugValues.bValidateAfterPush = true;
UE_LOG(LogVirtualization, Warning, TEXT("Cmdline has set the virtualization system to pull each payload after pushing to either local or persistent storage"));
}
FString CmdlineGraphName;
if (IsCmdLineValueSet(TEXT("-VABackendGraph="), TEXT("-VA-BackendGraph="), CmdlineGraphName))
{
UE_LOG(LogVirtualization, Display, TEXT("Backend graph overriden from the cmdline: '%s'"), *CmdlineGraphName);
BackendGraphName = CmdlineGraphName;
}
FString MissOptions;
if (IsCmdLineValueSet(TEXT("-VAMissBackends="), TEXT("-VA-MissBackends="), MissOptions))
{
MissOptions.ParseIntoArray(DebugValues.MissBackends, TEXT("+"), true);
UE_LOG(LogVirtualization, Warning, TEXT("Cmdline has disabled payload pulling for the following backends:"));
for (const FString& Backend : DebugValues.MissBackends)
{
UE_LOG(LogVirtualization, Warning, TEXT("\t%s"), *Backend);
}
}
DebugValues.MissChance = 0.0f;
if (IsCmdLineValueSet(TEXT("-VAMissChance="), TEXT("-VA-MissChance="), DebugValues.MissChance))
{
DebugValues.MissChance = FMath::Clamp(DebugValues.MissChance, 0.0f, 100.0f);
UE_LOG(LogVirtualization, Warning, TEXT("Cmdline has set a %.1f%% chance of a payload pull failing"), DebugValues.MissChance);
}
}
void FVirtualizationManager::RegisterConsoleCommands()
{
{
#if UE_USE_GLOBAL_CVAR
IConsoleVariable* Handle = IConsoleManager::Get().FindConsoleVariable(TEXT("VA.AllowPkgVirtualization"));
if (Handle != nullptr)
{
auto Callback = [this](IConsoleVariable* CVar)
{
this->bAllowPackageVirtualization = CVar->GetBool();
if (this->bAllowPackageVirtualization)
{
UE_LOG(LogVirtualization, Display, TEXT("The virtualization process has been enabled via the cvar 'VA.SkipPkgVirtualization'"));
}
else
{
UE_LOG(LogVirtualization, Display, TEXT("The virtualization process has been disabled via the cvar 'VA.SkipPkgVirtualization'"));
}
};
FDelegateHandle CallbackHandle = Handle->OnChangedDelegate().AddLambda(MoveTemp(Callback));
if (bAllowPackageVirtualization != Handle->GetBool())
{
Callback(Handle);
}
DebugValues.ConsoleDelegateHandles.Add({ Handle, CallbackHandle });
}
else
{
UE_LOG(LogVirtualization, Warning, TEXT("CVar VA.AllowPkgVirtualization could not be found and will not function"));
}
#else
bool bOriginalValue = bAllowPackageVirtualization;
IConsoleVariable* Handle = IConsoleManager::Get().RegisterConsoleVariableRef(
TEXT("VA.AllowPkgVirtualization"),
bAllowPackageVirtualization,
TEXT("When true submitting packages in the editor will no longer trigger the virtualization process")
);
auto Callback = [](IConsoleVariable* CVar)
{
if (CVar->GetBool())
{
UE_LOG(LogVirtualization, Display, TEXT("The virtualization process has been enabled via the cvar 'VA.SkipPkgVirtualization'"));
}
else
{
UE_LOG(LogVirtualization, Display, TEXT("The virtualization process has been disabled via the cvar 'VA.SkipPkgVirtualization'"));
}
};
// Log the change if the cvar was modified on the commandline
if (bOriginalValue != bAllowPackageVirtualization)
{
Callback(Handle);
}
Handle->OnChangedDelegate().AddLambda(MoveTemp(Callback));
DebugValues.ConsoleObjects.Add(Handle);
#endif // UE_USE_GLOBAL_CVAR
}
DebugValues.ConsoleObjects.Add(IConsoleManager::Get().RegisterConsoleCommand(
TEXT("VA.MissBackends"),
TEXT("A debug commnad which can be used to disable payload pulling on one or more backends"),
FConsoleCommandWithArgsAndOutputDeviceDelegate::CreateRaw(this, &FVirtualizationManager::OnUpdateDebugMissBackendsFromConsole)
));
DebugValues.ConsoleObjects.Add(IConsoleManager::Get().RegisterConsoleCommand(
TEXT("VA.MissChance"),
TEXT("A debug command which can be used to set the chance that a payload pull will fail"),
FConsoleCommandWithArgsAndOutputDeviceDelegate::CreateRaw(this, &FVirtualizationManager::OnUpdateDebugMissChanceFromConsole)
));
DebugValues.ConsoleObjects.Add(IConsoleManager::Get().RegisterConsoleCommand(
TEXT("VA.MissCount"),
TEXT("A debug command which can be used to cause the next X number of payload pulls to fail"),
FConsoleCommandWithArgsAndOutputDeviceDelegate::CreateRaw(this, &FVirtualizationManager::OnUpdateDebugMissCountFromConsole)
));
DebugValues.ConsoleObjects.Add(IConsoleManager::Get().RegisterConsoleVariableRef(
TEXT("VA.SingleThreaded"),
DebugValues.bSingleThreaded,
TEXT("When set the asset virtualization system will only access backends in a single threaded manner")
));
DebugValues.ConsoleObjects.Add(IConsoleManager::Get().RegisterConsoleVariableRef(
TEXT("VA.ValidatePushes"),
DebugValues.bValidateAfterPush,
TEXT("When set the asset virtualization system will pull each payload after pushing to either local or persistent storage")
));
}
void FVirtualizationManager::OnUpdateDebugMissBackendsFromConsole(const TArray<FString>& Args, FOutputDevice& OutputDevice)
{
if (Args.IsEmpty())
{
OutputDevice.Log(TEXT("VA.MissBackends command help"));
OutputDevice.Log(TEXT("This command allows you to disable the pulling of payloads by specific backends"));
OutputDevice.Log(TEXT(""));
OutputDevice.Log(TEXT("Commands:"));
OutputDevice.Log(TEXT("VA.MissBackends reset - Empties the list of backends, everything will function normally"));
OutputDevice.Log(TEXT("VA.MissBackends list - Prints the list of backends affected"));
OutputDevice.Log(TEXT("VA.MissBackends set Name0 Name1 - List each backend that you want to fail to pull payloads"));
OutputDevice.Log(TEXT("VA.MissBackends set All - All backends will fail to pull payloads"));
OutputDevice.Log(TEXT(""));
OutputDevice.Log(TEXT("Valid backend names:"));
for (const TUniquePtr<IVirtualizationBackend>& Backend : AllBackends)
{
OutputDevice.Logf(TEXT("\t%s"), *Backend->GetConfigName());
}
}
else if (Args.Num() == 1)
{
if (Args[0] == TEXT("reset"))
{
DebugValues.MissBackends.Empty();
UpdateBackendDebugState();
}
else if (Args[0] == TEXT("list"))
{
if (!DebugValues.MissBackends.IsEmpty())
{
OutputDevice.Log(TEXT("Disabled backends:"));
for (const FString& Backend : DebugValues.MissBackends)
{
OutputDevice.Logf(TEXT("\t%s"), *Backend);
}
}
else
{
OutputDevice.Log(TEXT("No backends are disabled"));
}
}
else
{
OutputDevice.Log(ELogVerbosity::Error, TEXT("Invalid args for the VA.MissBackends command!"));
}
}
else if (Args[0] == TEXT("set"))
{
DebugValues.MissBackends.Empty(Args.Num() - 1);
for (int32 Index = 1; Index < Args.Num(); ++Index)
{
DebugValues.MissBackends.Add(Args[Index]);
}
UpdateBackendDebugState();
}
else
{
OutputDevice.Log(ELogVerbosity::Error, TEXT("Invalid args for the VA.MissBackends command!"));
}
}
void FVirtualizationManager::OnUpdateDebugMissChanceFromConsole(const TArray<FString>& Args, FOutputDevice& OutputDevice)
{
if (Args.IsEmpty())
{
OutputDevice.Log(TEXT("VA.MissChance command help"));
OutputDevice.Log(TEXT("This command allows you to set the chance (in percent) that a payload pull request will just fail"));
OutputDevice.Log(TEXT(""));
OutputDevice.Log(TEXT("Commands:"));
OutputDevice.Log(TEXT("VA.MissChance show - prints the current miss percent chance"));
OutputDevice.Log(TEXT("VA.MissChance set Num - Sets the miss percent chance to the given value"));
}
else if (Args.Num() == 1 && Args[0] == TEXT("show"))
{
OutputDevice.Logf(TEXT("Current debug miss chance: %.1f%%"), DebugValues.MissChance);
}
else if (Args.Num() == 2 && Args[0] == TEXT("set"))
{
if (::LexTryParseString(DebugValues.MissChance, *Args[1]))
{
DebugValues.MissChance = FMath::Clamp(DebugValues.MissChance, 0.0f, 100.0f);
OutputDevice.Logf(TEXT("Current debug miss chance set to %.1f%%"), DebugValues.MissChance);
}
else
{
DebugValues.MissChance = 0.0f;
OutputDevice.Log(ELogVerbosity::Error, TEXT("Invalid value, current debug miss chance reset to 0.0%"));
}
}
else
{
OutputDevice.Log(ELogVerbosity::Error, TEXT("Invalid args for the VA.MissChance command!"));
}
}
void FVirtualizationManager::OnUpdateDebugMissCountFromConsole(const TArray<FString>& Args, FOutputDevice& OutputDevice)
{
if (Args.IsEmpty())
{
OutputDevice.Log(TEXT("VA.MissCount command help"));
OutputDevice.Log(TEXT("This command allows you to set the next X number of payload pulls to fail"));
OutputDevice.Log(TEXT(""));
OutputDevice.Log(TEXT("Commands:"));
OutputDevice.Log(TEXT("VA.MissCount show - prints the current number of future payload pulls that will fail"));
OutputDevice.Log(TEXT("VA.MissChance set Num - Sets the number of future payload pulls to fail"));
}
else if (Args.Num() == 1 && Args[0] == TEXT("show"))
{
// DebugMissCount could end up negative if many threads are pulling at once, so clamp to 0 as the min value
const int32 Value = FMath::Max(DebugValues.MissCount.load(std::memory_order_relaxed), 0);
OutputDevice.Logf(TEXT("The next '%d' payload pulls will fail"), Value);
}
else if (Args.Num() == 2 && Args[0] == TEXT("set"))
{
int32 ValueToSet = 0;
if (::LexTryParseString(ValueToSet, *Args[1]))
{
DebugValues.MissCount.store(ValueToSet, std::memory_order_relaxed);
OutputDevice.Logf(TEXT("The next '%d' payload pulls have been set to fail"), ValueToSet);
}
else
{
DebugValues.MissCount.store(0, std::memory_order_relaxed);
OutputDevice.Log(ELogVerbosity::Error, TEXT("Invalid value, the number of future payload pulls to fail has been set to zero"));
}
}
else
{
OutputDevice.Log(ELogVerbosity::Error, TEXT("Invalid args for the VA.MissCount command!"));
}
}
void FVirtualizationManager::UpdateBackendDebugState()
{
for (TUniquePtr<IVirtualizationBackend>& Backend : AllBackends)
{
const bool bDisable = ShouldDebugDisablePulling(Backend->GetConfigName());
Backend->SetOperationDebugState(IVirtualizationBackend::EOperations::Pull, bDisable);
}
}
bool FVirtualizationManager::ShouldDebugDisablePulling(FStringView BackendConfigName) const
{
if (DebugValues.MissBackends.IsEmpty())
{
return false;
}
if (DebugValues.MissBackends[0] == TEXT("All"))
{
return true;
}
for (const FString& Name : DebugValues.MissBackends)
{
if (Name == BackendConfigName)
{
return true;
}
}
return false;
}
bool FVirtualizationManager::ShouldDebugFailPulling()
{
// We don't want to decrement on every function call to avoid DebugMissCount
// underflowing, so we only try to decrement if the count is positive.
// It doesn't really matter if the value ends up a little bit negative.
if (DebugValues.MissCount.load(std::memory_order_relaxed) > 0)
{
if (DebugValues.MissCount.fetch_sub(1, std::memory_order_relaxed) > 0)
{
return true;
}
}
if (DebugValues.MissChance == 0.0f)
{
return false;
}
else
{
// Could consider adding a lock here, although FRandomStream
// is thread safe, many threads hitting it could cause a few
// threads to get the same results.
// Since this is a debug function and the percent is only a
// rough guide, adding a lock is considered overkill. This
// should only be done if in the future we decide that we want
// more accuracy.
static FRandomStream RandomStream(NAME_None);
const float RandValue = RandomStream.FRand() * 100.0f;
return RandValue <= DebugValues.MissChance;
}
}
void FVirtualizationManager::MountBackends(const FConfigFile& ConfigFile)
{
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
TRACE_CPUPROFILER_EVENT_SCOPE(FVirtualizationManager::MountBackends);
const FRegistedFactories FactoryLookupTable = FindBackendFactories();
UE_LOG(LogVirtualization, Verbose, TEXT("Found %d backend factories"), FactoryLookupTable.Num());
const TCHAR* GraphName = *BackendGraphName;
if(!ConfigFile.DoesSectionExist(GraphName))
{
UE_LOG(LogVirtualization, Fatal, TEXT("Unable to find the backend graph: '%s' [ini=%s]."), GraphName, *GEngineIni);
}
UE_LOG(LogVirtualization, Display, TEXT("Mounting virtualization backend graph: '%s'"), GraphName);
// It is important to parse the local storage hierarchy first so those backends will show up before the
// persistent storage backends in 'PullEnabledBackends'.
ParseHierarchy(ConfigFile, GraphName, TEXT("CacheStorageHierarchy"), TEXT("LocalStorageHierarchy"), FactoryLookupTable, CacheStorageBackends);
ParseHierarchy(ConfigFile, GraphName, TEXT("PersistentStorageHierarchy"), nullptr, FactoryLookupTable, PersistentStorageBackends);
// Apply and disabled backends from the command line
UpdateBackendDebugState();
}
void FVirtualizationManager::ParseHierarchy(const FConfigFile& ConfigFile, const TCHAR* GraphName, const TCHAR* HierarchyKey, const TCHAR* LegacyHierarchyKey, const FRegistedFactories& FactoryLookupTable, FBackendArray& PushArray)
{
bool bFoundHierarchy = false;
FString HierarchyData;
if (LegacyHierarchyKey != nullptr && ConfigFile.GetValue(GraphName, LegacyHierarchyKey, HierarchyData))
{
UE_LOG(LogVirtualization, Warning, TEXT("\tFound legacy HierarchyKey '%s', rename to '%s'"), LegacyHierarchyKey, HierarchyKey);
bFoundHierarchy = true;
}
else if (ConfigFile.GetValue(GraphName, HierarchyKey, HierarchyData))
{
bFoundHierarchy = true;
}
if (bFoundHierarchy)
{
if (HierarchyData.IsEmpty())
{
UE_LOG(LogVirtualization, Fatal, TEXT("\tThe '%s' entry for backend graph '%s' is empty [ini=%s]."), HierarchyKey, GraphName, *GEngineIni);
}
const TArray<FString> Entries = ParseEntries(HierarchyData);
UE_LOG(LogVirtualization, Display, TEXT("\tThe '%s' has %d backend(s)"), HierarchyKey, Entries.Num());
for (const FString& Entry : Entries)
{
CreateBackend(ConfigFile, GraphName, Entry, FactoryLookupTable, PushArray);
}
}
else
{
UE_LOG(LogVirtualization, Display, TEXT("\tNo entries for '%s' in the content virtualization backend graph '%s' [ini=%s]."), HierarchyKey, GraphName, *GEngineIni);
}
}
bool FVirtualizationManager::CreateBackend(const FConfigFile& ConfigFile, const TCHAR* GraphName, const FString& ConfigEntryName, const FRegistedFactories& FactoryLookupTable, FBackendArray& PushArray)
{
// All failures in this method are considered fatal, however it still returns true/false in case we decide
// to be more forgiving in the future.
UE_LOG(LogVirtualization, Display, TEXT("Mounting backend entry '%s'"), *ConfigEntryName);
FString BackendData;
if (!ConfigFile.GetValue(GraphName, *ConfigEntryName, BackendData))
{
UE_LOG(LogVirtualization, Fatal, TEXT("Unable to find the entry '%s' in the content virtualization backend graph '%s' [ini=%s]."), *ConfigEntryName, GraphName, *GEngineIni);
return false;
}
FString BackendType;
if (FParse::Value(*BackendData, TEXT("Type="), BackendType) && !BackendType.IsEmpty())
{
// Put the rest of the ini file entry into a string to pass to the backend.
FString Cmdine = BackendData.RightChop(BackendData.Find(BackendType) + BackendType.Len());
Cmdine.RemoveFromEnd(TEXT(")"));
UE::Virtualization::IVirtualizationBackendFactory* const* FactoryPtr = FactoryLookupTable.Find(FName(BackendType));
if (FactoryPtr != nullptr && *FactoryPtr != nullptr)
{
IVirtualizationBackendFactory* Factory = *FactoryPtr;
TUniquePtr<IVirtualizationBackend> Backend = Factory->CreateInstance(ProjectName, ConfigEntryName);
if (Backend == nullptr)
{
UE_LOG(LogVirtualization, Fatal, TEXT("IVirtualizationBackendFactory '%s' failed to create an instance!"), *Factory->GetName().ToString());
return false;
}
if (Backend->Initialize(Cmdine))
{
// The read only flag can be applied to any backend so we check for it and apply it at this point
bool bReadOnly = false;
FParse::Bool(*Cmdine, TEXT("ReadOnly="), bReadOnly);
if (bReadOnly && Backend->DisableOperation(IVirtualizationBackend::EOperations::Push))
{
UE_LOG(LogVirtualization, Display, TEXT("The backend '%s' was set to readonly by the config file!"), *Backend->GetDebugName());
}
AddBackend(MoveTemp(Backend), PushArray);
}
else
{
UE_LOG(LogVirtualization, Fatal, TEXT("Backend '%s' reported errors when initializing"), *ConfigEntryName);
return false;
}
}
else
{
UE_LOG(LogVirtualization, Fatal, TEXT("No backend factory found that can create the type '%s'"), *BackendType);
return false;
}
}
else
{
UE_LOG(LogVirtualization, Fatal, TEXT("No 'Type=' entry found for '%s' in the config file"), *ConfigEntryName);
return false;
}
return true;
}
void FVirtualizationManager::AddBackend(TUniquePtr<IVirtualizationBackend> Backend, FBackendArray& PushArray)
{
checkf(!AllBackends.Contains(Backend), TEXT("Adding the same virtualization backend (%s) multiple times!"), *Backend->GetDebugName());
// Move ownership of the backend to AllBackends
AllBackends.Add(MoveTemp(Backend));
// Get a reference pointer to use in the other backend arrays
IVirtualizationBackend* BackendRef = AllBackends.Last().Get();
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
check(BackendRef != nullptr);
if (BackendRef->IsOperationSupported(IVirtualizationBackend::EOperations::Pull))
{
PullEnabledBackends.Add(BackendRef);
}
if (BackendRef->IsOperationSupported(IVirtualizationBackend::EOperations::Push))
{
PushArray.Add(BackendRef);
}
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
// We immediately try to connect once the backend has been added.
// In the future this will be made async to avoid blocking the GameThread on startup
if (!bLazyInitConnections)
{
BackendRef->Connect();
}
else
{
bPendingBackendConnections = true;
}
COOK_STAT(Profiling::CreateStats(*BackendRef));
}
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
void FVirtualizationManager::EnsureBackendConnections()
{
if (bPendingBackendConnections)
{
// Only allow one thread to initialize the system at a time
static FCriticalSection InitCS;
FScopeLock _(&InitCS);
if (bPendingBackendConnections)
{
for (const TUniquePtr<IVirtualizationBackend>& Backend : AllBackends)
{
Backend->Connect();
}
bPendingBackendConnections = false;
}
}
}
void FVirtualizationManager::CachePayloads(TArrayView<FPushRequest> Requests, const IVirtualizationBackend* BackendSource, IVirtualizationBackend::EPushFlags Flags)
{
TRACE_CPUPROFILER_EVENT_SCOPE(FVirtualizationManager::CachePayload);
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
check(!bPendingBackendConnections);
// We start caching at the first (assumed to be fastest) local cache backend.
for (IVirtualizationBackend* BackendToCache : CacheStorageBackends)
{
// We stop once we reach the backend that the payloads were first pulled from
if (BackendToCache == BackendSource)
{
return;
}
const bool bResult = TryCacheDataToBackend(*BackendToCache, Requests, Flags);
if (!bResult)
{
for (const FPushRequest& Request : Requests)
{
UE_LOG(LogVirtualization, Warning, TEXT("Failed to cache payload '%s' to backend '%s'"), *LexToString(Request.GetIdentifier()), *BackendToCache->GetDebugName());
}
}
// Debug operation to validate that the payload we just cached can be retrieved from storage
if (DebugValues.bValidateAfterPush && bResult && BackendToCache->IsOperationSupported(IVirtualizationBackend::EOperations::Pull))
{
for (const FPushRequest& Request : Requests)
{
FPullRequest ValidationRequest(Request.GetIdentifier());
PullDataFromBackend(*BackendToCache, MakeArrayView(&ValidationRequest, 1));
checkf(Request.GetPayload().GetRawHash() == ValidationRequest.GetPayload().GetRawHash(),
TEXT("[%s] Failed to pull payload '%s' after it was cached to backend"),
*BackendToCache->GetDebugName(),
*LexToString(Request.GetIdentifier()));
}
}
}
}
bool FVirtualizationManager::TryCacheDataToBackend(IVirtualizationBackend& Backend, TArrayView<FPushRequest> Requests, IVirtualizationBackend::EPushFlags Flags)
{
COOK_STAT(FCookStats::CallStats & Stats = Profiling::GetCacheStats(Backend));
COOK_STAT(FCookStats::FScopedStatsCounter Timer(Stats));
COOK_STAT(Timer.TrackCyclesOnly());
Refactor the VA pushing API so that we only need to implement a single path #rb Per.Larsson #jira UE-163103 #rnx #preflight 6318989c2b7fe03eb664e9f0 ### VirtualizationSystem/VirtualizationManager - Added an overload of ::Push taking just one FPUshRequest so that people don't have to keep adding MakeArrayView boiler plate when pushing a single request - Change the order of the last two parameters for the raw ::Push call as this will group all of the payload specific parameters together and leave the target storage type at the end. It is unlikely that anyone is calling the older version but it has been deprecated for safety. ### IVirtualizationBackend - The none FPushRequest overload of ::PushData is no longer virtual, it just converts the parameters to FPushRequest and calls that overload instead. In this way we now only have one pushing code path in our backends. We could probably look into removing this overload at this point (since the higher level IVirtualizationSystem will now convert all push requests into a FPushRequest form) but it is not considered worth it at the moment when the simple overload covers our needs. - Removed EPushResult in favour of just returning true/false for the overall operation.If the caller needs a more detailed breakdown then they will have to use an overload that takes an FPushRequest over raw parameters. -- At the moment FPushRequest does not contain a full breakdown of what happened, so with this submit we are effectively losing the ability to find out if the payload was already in the backends or not, however the batch version of push was already not returning this info so it is not a big loss. Fixing FPushRequest to return a better break down of what happened will be done in UE-160942 - Removed the none batch Push paths from the source control and ddc backends as they already supported batch pushing. - File backend needed to be converted to supporting batch pushing, which is pretty much the same code as before except we need to iterate over the container of FPushRequests. -- The backend does not early out on error as it tends to be quite fast. We might want to consider an official policy for the VA system, if we should early out of errors or not. [CL 21907558 by paul chipchase in ue5-main branch]
2022-09-08 19:35:36 -04:00
if (Backend.PushData(Requests, Flags))
{
#if ENABLE_COOK_STATS
Timer.AddHit(0);
const bool bIsInGameThread = IsInGameThread();
for (const FPushRequest& Request : Requests)
{
if (Request.GetResult().WasPushed())
{
Stats.Accumulate(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Counter, 1l, bIsInGameThread);
Stats.Accumulate(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Bytes, Request.GetPayload().GetCompressedSize(), bIsInGameThread);
}
}
#endif // ENABLE_COOK_STATS
Refactor the VA pushing API so that we only need to implement a single path #rb Per.Larsson #jira UE-163103 #rnx #preflight 6318989c2b7fe03eb664e9f0 ### VirtualizationSystem/VirtualizationManager - Added an overload of ::Push taking just one FPUshRequest so that people don't have to keep adding MakeArrayView boiler plate when pushing a single request - Change the order of the last two parameters for the raw ::Push call as this will group all of the payload specific parameters together and leave the target storage type at the end. It is unlikely that anyone is calling the older version but it has been deprecated for safety. ### IVirtualizationBackend - The none FPushRequest overload of ::PushData is no longer virtual, it just converts the parameters to FPushRequest and calls that overload instead. In this way we now only have one pushing code path in our backends. We could probably look into removing this overload at this point (since the higher level IVirtualizationSystem will now convert all push requests into a FPushRequest form) but it is not considered worth it at the moment when the simple overload covers our needs. - Removed EPushResult in favour of just returning true/false for the overall operation.If the caller needs a more detailed breakdown then they will have to use an overload that takes an FPushRequest over raw parameters. -- At the moment FPushRequest does not contain a full breakdown of what happened, so with this submit we are effectively losing the ability to find out if the payload was already in the backends or not, however the batch version of push was already not returning this info so it is not a big loss. Fixing FPushRequest to return a better break down of what happened will be done in UE-160942 - Removed the none batch Push paths from the source control and ddc backends as they already supported batch pushing. - File backend needed to be converted to supporting batch pushing, which is pretty much the same code as before except we need to iterate over the container of FPushRequests. -- The backend does not early out on error as it tends to be quite fast. We might want to consider an official policy for the VA system, if we should early out of errors or not. [CL 21907558 by paul chipchase in ue5-main branch]
2022-09-08 19:35:36 -04:00
return true;
}
else
{
return false;
}
}
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
bool FVirtualizationManager::TryPushDataToBackend(IVirtualizationBackend& Backend, TArrayView<FPushRequest> Requests)
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
{
COOK_STAT(FCookStats::CallStats & Stats = Profiling::GetPushStats(Backend));
COOK_STAT(FCookStats::FScopedStatsCounter Timer(Stats));
COOK_STAT(Timer.TrackCyclesOnly());
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
const bool bPushResult = Backend.PushData(Requests, IVirtualizationBackend::EPushFlags::None);
#if ENABLE_COOK_STATS
if (bPushResult)
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
{
Timer.AddHit(0);
const bool bIsInGameThread = IsInGameThread();
for (const FPushRequest& Request : Requests)
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
{
if (Request.GetResult().WasPushed())
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
{
Stats.Accumulate(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Counter, 1l, bIsInGameThread);
When virtualizing payloads we now load the payloads from disk on demand rather than all at once. This allows us to avoid memory spikes when virtualizing large amounts of data. #rb Per.Larsson #rnx #jira UE-151000 #preflight 627271c83b2ed6f85363f53a - In the old code when submitting packages for virtualization we would load all local payloads into memory then pass them to the virtualization system to be pushed to persistent storage. This works fine for an average users submits but when resaving large projects we can have submits with thousands of packages containing gigabytes of payloads. - FPushRequest has been changed to accept either a payload directly (in the form of FCompressedBuffer) or accept a reference to a IPayloadProvider which will return the payload when asked. - Most of the existing backends make no use of the batched pushing feature and only push one payload at a time. The default implementation of this will be to ask each request one at a time for the payload and then pass it to the backend for a single push. If the IPayloadProvider is being used we will therefor only ever have one payload loaded at a time avoiding memory spikes. - The source control backend currently does implement the batched pushing feature. This backend writes each payload to disk before submitting them to perforce, so all we have to do is make sure that request one payload, write it to disk, then discard the payload to avoid memory spikes. - This change required that FPushRequest make it's members private and provide accessors to them, as the caller shouldn't need to care if the payload is loaded or comes via the provider. - NOTE that this implementation is less efficient if we have packages containing many different payloads as we will end up opening the package, parsing the trailer then load a payload many times over, where as the original code would load all payloads from the file in one go. In practice, given the overhead of the source control backend this didn't make a huge difference and is probably not worth the effort to optimize at this point. [CL 20040609 by paul chipchase in ue5-main branch]
2022-05-04 08:58:50 -04:00
Stats.Accumulate(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Bytes, Request.GetPayloadSize(), bIsInGameThread);
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
}
}
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
}
#endif // ENABLE_COOK_STATS
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
return bPushResult;
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
}
void FVirtualizationManager::PullDataFromAllBackends(TArrayView<FPullRequest> Requests)
{
if (ShouldDebugFailPulling())
{
UE_LOG(LogVirtualization, Verbose, TEXT("Debug miss chance (%.1f%%) invoked"), DebugValues.MissChance);
return;
}
FPullRequestCollection RequestsCollection(Requests);
while(true)
{
for (IVirtualizationBackend* Backend : PullEnabledBackends)
{
check(Backend != nullptr);
if (Backend->IsOperationDebugDisabled(IVirtualizationBackend::EOperations::Pull))
{
UE_LOG(LogVirtualization, Verbose, TEXT("Pulling from backend '%s' is debug disabled"), *Backend->GetDebugName());
continue;
}
if (Backend->GetConnectionStatus() != IVirtualizationBackend::EConnectionStatus::Connected)
{
UE_LOG(LogVirtualization, Verbose, TEXT("Cannot pull from backend '%s' as it is not connected"), *Backend->GetDebugName());
continue;
}
PullDataFromBackend(*Backend, RequestsCollection.GetRequests());
const bool bShouldCache = EnumHasAllFlags(CachingPolicy, ECachingPolicy::CacheOnPull);
TArray<FPushRequest> PayloadsToCache = RequestsCollection.OnPullCompleted(*Backend, bShouldCache);
if (!PayloadsToCache.IsEmpty())
{
const IVirtualizationBackend::EPushFlags CacheOnPullFlags = bForceCachingOnPull ? IVirtualizationBackend::EPushFlags::Force
: IVirtualizationBackend::EPushFlags::None;
CachePayloads(PayloadsToCache, Backend, CacheOnPullFlags);
}
// We can early out if there is no more requests to make
if (RequestsCollection.IsWorkComplete())
{
break;
}
}
if (RequestsCollection.IsWorkComplete())
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
{
return; // All payloads pulled
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
}
else if (OnPayloadPullError() != ErrorHandlingResult::Retry)
{
return; // Some payloads failed to pull
}
}
}
void FVirtualizationManager::PullDataFromBackend(IVirtualizationBackend& Backend, TArrayView<FPullRequest> Requests)
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
{
COOK_STAT(FCookStats::CallStats & Stats = Profiling::GetPullStats(Backend));
COOK_STAT(FCookStats::FScopedStatsCounter Timer(Stats));
COOK_STAT(Timer.TrackCyclesOnly());
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
Backend.PullData(Requests, IVirtualizationBackend::EPullFlags::None);
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
#if ENABLE_COOK_STATS
const bool bIsInGameThread = IsInGameThread();
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
for (const FPullRequest& Request : Requests)
{
Timer.AddHit(0);
if (Request.IsSuccess())
{
Stats.Accumulate(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Counter, 1l, bIsInGameThread);
Stats.Accumulate(FCookStats::CallStats::EHitOrMiss::Hit, FCookStats::CallStats::EStatType::Bytes, Request.GetPayload().GetCompressedSize(), bIsInGameThread);
}
}
#endif //ENABLE_COOK_STATS
}
Add a config file option to allow payloads stored in .umap and associated "_builddata.uasset" files to be filtered from the virtualization process. This option defaults to true. #rb Per.Larsson #jira UE-156750 #rnx #preflight 62f212e13b773d04161ee7dd ### Problem - The payloads stored in map files tend to change more than other assets and would cause a lot more churn in the VA system. - Some other systems like the landscape component are not able to sensibly continue if their payloads cannot be accessed (heightmaps for exmaple) and would prefer not to allow virtualization. - As a short term fix we need an option to disable the virtualization on all payloads in map files. Future improvements to the filtering system will allow systems to more easily opt their payloads out of virtualization. When this is functional we might want to change the default from true to false. ### Feature - The config optionf for this filtering is "[Core.VirtualizationModule]FilterMapContent=True" - Testing if the owning UObject for a payload is in a umap can get tricky, because we not only need to check the umap but we also need to check if it is in a "_builddata.uasset" file, which is an additional file we store next to a umap containing things like lightmaps etc. - At the moment we check for this by finding the outermost object for the given owner and check to see if it is a ULevel, UWorld or UMapBuildDataRegistry. This is a bit of a kludge but the types we need to check against are not accessible by this module and making them accessible will pull in a lot of dependencies that we'd prefer not to add. -- One improvement might be to tag the FLinkerSave with the info we need and passing that into the serialization process rather than trying to work it out ourselves but I am wary of making that change until we are 100% sure that we want to keep this feature. ### Refactor - Removed IVirtualizationSystem::IsDisabledForObject and replaced it with ::FilterPayload which can return multiple reasons for preventing a payload from virtualizing. (the method was added during 5.1 development so it should be fine to just replace it without deprecation) -- The original behaviour for FVirtualizationManager::IsDisabledForObject has been moved to FVirtualizationManager::ShouldVirtualizeAsset - Added a new header to declare enums/types used by the various parts of the virtualization system and started by moving EPayloadFilterReason there from the package trailer header. This allows both the core API and PackageTrailer to use EPayloadFilterReason without creating overburdened header dependencies. -- EPayloadFilterReason has moved from the UE namespace to UE::Virtualization so the package trailer code needed updating accordingly. - EditorBulkData will ask the virtualization system for the base filter reason, then add it's own reasons if UE_ENABLE_VIRTUALIZATION_TOGGLE is enabled. This bit of code will be removed for 5.1 [CL 21283179 by paul chipchase in ue5-main branch]
2022-08-09 07:51:55 -04:00
FVirtualizationManager::ErrorHandlingResult FVirtualizationManager::OnPayloadPullError()
{
if (bUseLegacyErrorHandling)
{
return ErrorHandlingResult::AcceptFailedPayloads;
}
static FCriticalSection CriticalSection;
if (CriticalSection.TryLock())
{
const FText Title(LOCTEXT("VAPullTitle", "Failed to pull virtualized data!"));
FTextBuilder MsgBuilder;
MsgBuilder.AppendLine(LOCTEXT("VAPullMsgHeader", "Failed to pull payload(s) from virtualization storage and allowing the editor to continue could corrupt data!"));
if (!PullErrorAdditionalMsg.IsEmpty())
{
MsgBuilder.AppendLine(FString(TEXT("")));
MsgBuilder.AppendLine(PullErrorAdditionalMsg);
}
MsgBuilder.AppendLine(FString(TEXT("")));
MsgBuilder.AppendLine(LOCTEXT("VAPullMsgYes", "[Yes] Retry pulling the data"));
MsgBuilder.AppendLine(LOCTEXT("VAPullMsgNo", "[No] Quit the editor"));
const FText Message = MsgBuilder.ToText();
EAppReturnType::Type Result = FMessageDialog::Open(EAppMsgType::YesNo, EAppReturnType::No, Message, Title);
if (Result == EAppReturnType::No)
{
UE_LOG(LogVirtualization, Error, TEXT("Failed to pull payloads from persistent storage and the connection could not be re-established, exiting..."));
GIsCriticalError = 1;
FPlatformMisc::RequestExit(true);
}
CriticalSection.Unlock();
}
else
{
FScopeLock _(&CriticalSection);
}
return ErrorHandlingResult::Retry;
}
Add a config file option to allow payloads stored in .umap and associated "_builddata.uasset" files to be filtered from the virtualization process. This option defaults to true. #rb Per.Larsson #jira UE-156750 #rnx #preflight 62f212e13b773d04161ee7dd ### Problem - The payloads stored in map files tend to change more than other assets and would cause a lot more churn in the VA system. - Some other systems like the landscape component are not able to sensibly continue if their payloads cannot be accessed (heightmaps for exmaple) and would prefer not to allow virtualization. - As a short term fix we need an option to disable the virtualization on all payloads in map files. Future improvements to the filtering system will allow systems to more easily opt their payloads out of virtualization. When this is functional we might want to change the default from true to false. ### Feature - The config optionf for this filtering is "[Core.VirtualizationModule]FilterMapContent=True" - Testing if the owning UObject for a payload is in a umap can get tricky, because we not only need to check the umap but we also need to check if it is in a "_builddata.uasset" file, which is an additional file we store next to a umap containing things like lightmaps etc. - At the moment we check for this by finding the outermost object for the given owner and check to see if it is a ULevel, UWorld or UMapBuildDataRegistry. This is a bit of a kludge but the types we need to check against are not accessible by this module and making them accessible will pull in a lot of dependencies that we'd prefer not to add. -- One improvement might be to tag the FLinkerSave with the info we need and passing that into the serialization process rather than trying to work it out ourselves but I am wary of making that change until we are 100% sure that we want to keep this feature. ### Refactor - Removed IVirtualizationSystem::IsDisabledForObject and replaced it with ::FilterPayload which can return multiple reasons for preventing a payload from virtualizing. (the method was added during 5.1 development so it should be fine to just replace it without deprecation) -- The original behaviour for FVirtualizationManager::IsDisabledForObject has been moved to FVirtualizationManager::ShouldVirtualizeAsset - Added a new header to declare enums/types used by the various parts of the virtualization system and started by moving EPayloadFilterReason there from the package trailer header. This allows both the core API and PackageTrailer to use EPayloadFilterReason without creating overburdened header dependencies. -- EPayloadFilterReason has moved from the UE namespace to UE::Virtualization so the package trailer code needed updating accordingly. - EditorBulkData will ask the virtualization system for the base filter reason, then add it's own reasons if UE_ENABLE_VIRTUALIZATION_TOGGLE is enabled. This bit of code will be removed for 5.1 [CL 21283179 by paul chipchase in ue5-main branch]
2022-08-09 07:51:55 -04:00
bool FVirtualizationManager::ShouldVirtualizeAsset(const UObject* OwnerObject) const
{
if (OwnerObject == nullptr)
{
return true;
}
const UClass* OwnerClass = OwnerObject->GetClass();
if (OwnerClass == nullptr)
{
// TODO: Not actually sure if the class being nullptr is reasonable or if we should warn/error here?
return true;
}
const FName ClassName = OwnerClass->GetFName();
return DisabledAssetTypes.Find(ClassName) == nullptr;
}
bool FVirtualizationManager::ShouldVirtualizePackage(const FPackagePath& PackagePath) const
{
TRACE_CPUPROFILER_EVENT_SCOPE(FVirtualizationManager::ShouldVirtualizePackage);
// We require a valid mounted path for filtering
if (!PackagePath.IsMountedPath())
{
return true;
}
TStringBuilder<256> PackageName;
PackagePath.AppendPackageName(PackageName);
TStringBuilder<64> MountPointName;
TStringBuilder<256> MountPointPath;
TStringBuilder<256> RelativePath;
if (!FPackageName::TryGetMountPointForPath(PackageName, MountPointName, MountPointPath, RelativePath))
{
return true;
}
// Do not virtualize engine content
if (MountPointName.ToView() == TEXT("/Engine/") || FPaths::IsUnderDirectory(MountPointPath.ToString(), FPaths::EnginePluginsDir()))
{
return false;
}
const UVirtualizationFilterSettings* Settings = GetDefault<UVirtualizationFilterSettings>();
if (Settings != nullptr)
{
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
auto DoesMatch = [](const TArray<FString>& Paths, const FStringView& PackagePath) -> bool
{
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
for (const FString& PathToMatch : Paths)
{
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
if (PathToMatch.EndsWith(TEXT("/")))
{
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
// Directory path, exclude everything under it
if (PackagePath.StartsWith(PathToMatch))
{
return true;
}
}
else
{
// Path to an asset, exclude if it matches exactly
if (PackagePath == PathToMatch)
{
return true;
}
}
}
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
return false;
};
const FStringView PackageNameView = PackageName.ToView();
if (DoesMatch(Settings->ExcludePackagePaths, PackageNameView))
{
return false;
}
if (DoesMatch(Settings->IncludePackagePaths, PackageNameView))
{
return true;
}
}
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
// The package is not in any of the include/exclude paths so we use the default behavior
return ShouldVirtualizeAsDefault();
}
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
bool FVirtualizationManager::ShouldVirtualize(const FString& Context) const
{
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
// First see if we can convert the context from a raw string to a valid package path.
// If we can extract a package path then we should use the package filtering code
// path instead.
FPackagePath PackagePath;
if (FPackagePath::TryFromPackageName(Context, PackagePath))
{
return ShouldVirtualizePackage(PackagePath);
}
if (FPackagePath::TryFromMountedName(Context, PackagePath))
{
return ShouldVirtualizePackage(PackagePath);
}
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
// The package is not in any of the include/exclude paths so we use the default behavior
return ShouldVirtualizeAsDefault();
}
bool FVirtualizationManager::ShouldVirtualizeAsDefault() const
{
switch (FilteringMode)
{
case EPackageFilterMode::OptOut:
return true;
case EPackageFilterMode::OptIn:
return false;
default:
checkNoEntry();
return false;
}
}
void FVirtualizationManager::BroadcastEvent(TConstArrayView<FPullRequest> Requests, ENotification Event)
{
for (const FPullRequest& Request : Requests)
{
GetNotificationEvent().Broadcast(IVirtualizationSystem::PullEndedNotification, Request.GetIdentifier());
}
}
void FVirtualizationManager::GatherAnalytics(TArray<FAnalyticsEventAttribute>& Attributes) const
{
using namespace UE::Virtualization;
// Grab the Virtualization stats
if (IVirtualizationSystem::IsInitialized())
{
IVirtualizationSystem& System = IVirtualizationSystem::Get();
FPayloadActivityInfo PayloadActivityInfo = System.GetAccumualtedPayloadActivityInfo();
const FString BaseName = TEXT("Virtualization");
{
FString AttrName = BaseName + TEXT("_Enabled");
Attributes.Emplace(MoveTemp(AttrName), System.IsEnabled());
}
{
FString AttrName = BaseName + TEXT("_Cache_TimeSpent");
Attributes.Emplace(MoveTemp(AttrName), (double)PayloadActivityInfo.Cache.CyclesSpent * FPlatformTime::GetSecondsPerCycle());
}
{
FString AttrName = BaseName + TEXT("_Cache_PayloadCount");
Attributes.Emplace(MoveTemp(AttrName), (double)PayloadActivityInfo.Cache.PayloadCount);
}
{
FString AttrName = BaseName + TEXT("_Cache_TotalBytes");
Attributes.Emplace(MoveTemp(AttrName), (double)PayloadActivityInfo.Cache.TotalBytes);
}
{
FString AttrName = BaseName + TEXT("_Push_TimeSpent");
Attributes.Emplace(MoveTemp(AttrName), (double)PayloadActivityInfo.Push.CyclesSpent * FPlatformTime::GetSecondsPerCycle());
}
{
FString AttrName = BaseName + TEXT("_Push_PayloadCount");
Attributes.Emplace(MoveTemp(AttrName), (double)PayloadActivityInfo.Push.PayloadCount);
}
{
FString AttrName = BaseName + TEXT("_Push_TotalBytes");
Attributes.Emplace(MoveTemp(AttrName), (double)PayloadActivityInfo.Push.TotalBytes);
}
{
FString AttrName = BaseName + TEXT("_Pull_TimeSpent");
Attributes.Emplace(MoveTemp(AttrName), (double)PayloadActivityInfo.Pull.CyclesSpent * FPlatformTime::GetSecondsPerCycle());
}
{
FString AttrName = BaseName + TEXT("_Pull_PayloadCount");
Attributes.Emplace(MoveTemp(AttrName), (double)PayloadActivityInfo.Pull.PayloadCount);
}
{
FString AttrName = BaseName + TEXT("_Pull_TotalBytes");
Attributes.Emplace(MoveTemp(AttrName), (double)PayloadActivityInfo.Pull.TotalBytes);
}
}
}
} // namespace UE::Virtualization
#undef UE_INLINE_ALLOCATION_COUNT
#undef LOCTEXT_NAMESPACE