You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#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]
189 lines
5.3 KiB
C++
189 lines
5.3 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "VirtualizationDDCBackend.h"
|
|
|
|
#include "Misc/Parse.h"
|
|
#include "Virtualization/PayloadId.h"
|
|
#include "DerivedDataCache.h"
|
|
#include "DerivedDataCacheRecord.h"
|
|
#include "DerivedDataPayload.h"
|
|
#include "DerivedDataRequestOwner.h"
|
|
|
|
namespace UE::Virtualization
|
|
{
|
|
|
|
/** Utility function to help convert from UE::Virtualization types to UE::DerivedData::FPayload */
|
|
UE::DerivedData::FPayload ToDDCPayload(const FPayloadId& Id, const FCompressedBuffer& Payload)
|
|
{
|
|
UE::DerivedData::FPayloadId DDCPayloadId = UE::DerivedData::FPayloadId::FromHash(Id.GetIdentifier());
|
|
|
|
return UE::DerivedData::FPayload(DDCPayloadId, Payload);
|
|
}
|
|
|
|
FDDCBackend::FDDCBackend(FStringView ConfigName, FStringView InDebugName)
|
|
: IVirtualizationBackend(ConfigName, InDebugName, EOperations::Both)
|
|
, BucketName(TEXT("BulkData"))
|
|
, TransferPolicy(UE::DerivedData::ECachePolicy::None)
|
|
, QueryPolicy(UE::DerivedData::ECachePolicy::None)
|
|
{
|
|
|
|
}
|
|
|
|
bool FDDCBackend::Initialize(const FString& ConfigEntry)
|
|
{
|
|
TRACE_CPUPROFILER_EVENT_SCOPE(Initialize::Initialize);
|
|
|
|
if (!FParse::Value(*ConfigEntry, TEXT("Bucket="), BucketName))
|
|
{
|
|
UE_LOG(LogVirtualization, Fatal, TEXT("[%s] 'Bucket=' not found in the config file"), *GetDebugName());
|
|
}
|
|
|
|
bool bAllowLocal = true;
|
|
if (FParse::Bool(*ConfigEntry, TEXT("LocalStorage="), bAllowLocal))
|
|
{
|
|
UE_LOG(LogVirtualization, Log, TEXT("[%s] Use of local storage set to '%s"), *GetDebugName(), bAllowLocal ? TEXT("true") : TEXT("false"));
|
|
}
|
|
|
|
bool bAllowRemote = true;
|
|
if (FParse::Bool(*ConfigEntry, TEXT("RemoteStorage="), bAllowRemote))
|
|
{
|
|
UE_LOG(LogVirtualization, Log, TEXT("[%s] Use of remote storage set to '%s"), *GetDebugName(), bAllowRemote ? TEXT("true") : TEXT("false"));
|
|
}
|
|
|
|
if (!bAllowLocal && !bAllowRemote)
|
|
{
|
|
UE_LOG(LogVirtualization, Fatal, TEXT("[%s] LocalStorage and RemoteStorage cannot both be disabled"), *GetDebugName());
|
|
return false;
|
|
}
|
|
|
|
if (bAllowLocal)
|
|
{
|
|
TransferPolicy |= UE::DerivedData::ECachePolicy::Local;
|
|
QueryPolicy |= UE::DerivedData::ECachePolicy::QueryLocal;
|
|
}
|
|
|
|
if (bAllowRemote)
|
|
{
|
|
TransferPolicy |= UE::DerivedData::ECachePolicy::Remote;
|
|
QueryPolicy |= UE::DerivedData::ECachePolicy::QueryRemote;
|
|
}
|
|
|
|
Bucket = UE::DerivedData::FCacheBucket(BucketName);
|
|
|
|
return true;
|
|
}
|
|
|
|
EPushResult FDDCBackend::PushData(const FPayloadId& Id, const FCompressedBuffer& Payload, const FString& PackageContext)
|
|
{
|
|
TRACE_CPUPROFILER_EVENT_SCOPE(FDDCBackend::PushData);
|
|
|
|
if (DoesPayloadExist(Id))
|
|
{
|
|
UE_LOG(LogVirtualization, Verbose, TEXT("[%s] Already has a copy of the payload '%s'."), *GetDebugName(), *Id.ToString());
|
|
return EPushResult::PayloadAlreadyExisted;
|
|
}
|
|
|
|
UE::DerivedData::ICache& Cache = UE::DerivedData::GetCache();
|
|
|
|
UE::DerivedData::FCacheKey Key;
|
|
Key.Bucket = Bucket;
|
|
Key.Hash = Id.GetIdentifier();
|
|
|
|
UE::DerivedData::FPayload DDCPayload = ToDDCPayload(Id, Payload);
|
|
check(DDCPayload.GetRawHash() == Id.GetIdentifier());
|
|
|
|
UE::DerivedData::FCacheRecordBuilder RecordBuilder(Key);
|
|
RecordBuilder.SetValue(DDCPayload);
|
|
|
|
UE::DerivedData::FRequestOwner Owner(UE::DerivedData::EPriority::Blocking);
|
|
|
|
UE::DerivedData::FCachePutCompleteParams Result;
|
|
auto Callback = [&Result](UE::DerivedData::FCachePutCompleteParams&& Params)
|
|
{
|
|
Result = Params;
|
|
};
|
|
|
|
Cache.Put( {RecordBuilder.Build()},
|
|
TEXT("Mirage"), // TODO: Improve this when we start passing more context to push
|
|
TransferPolicy,
|
|
Owner,
|
|
MoveTemp(Callback));
|
|
|
|
Owner.Wait();
|
|
|
|
if (Result.Status == UE::DerivedData::EStatus::Ok)
|
|
{
|
|
return EPushResult::Success;
|
|
}
|
|
else
|
|
{
|
|
return EPushResult::Failed;
|
|
}
|
|
}
|
|
|
|
FCompressedBuffer FDDCBackend::PullData(const FPayloadId& Id)
|
|
{
|
|
TRACE_CPUPROFILER_EVENT_SCOPE(FDDCBackend::PullData);
|
|
|
|
UE::DerivedData::ICache& Cache = UE::DerivedData::GetCache();
|
|
|
|
UE::DerivedData::FCacheKey Key;
|
|
Key.Bucket = Bucket;
|
|
Key.Hash = Id.GetIdentifier();
|
|
|
|
UE::DerivedData::FRequestOwner Owner(UE::DerivedData::EPriority::Blocking);
|
|
|
|
FCompressedBuffer ResultData;
|
|
UE::DerivedData::EStatus ResultStatus;
|
|
|
|
auto Callback = [&ResultData, &ResultStatus](UE::DerivedData::FCacheGetCompleteParams&& Params)
|
|
{
|
|
ResultStatus = Params.Status;
|
|
if (ResultStatus == UE::DerivedData::EStatus::Ok)
|
|
{
|
|
ResultData = Params.Record.GetValuePayload().GetData();
|
|
}
|
|
};
|
|
|
|
Cache.Get( {Key},
|
|
TEXT("Mirage"), // TODO: Improve this when we start passing more context to push
|
|
TransferPolicy,
|
|
Owner,
|
|
MoveTemp(Callback));
|
|
|
|
Owner.Wait();
|
|
|
|
return ResultData;
|
|
}
|
|
|
|
bool FDDCBackend::DoesPayloadExist(const FPayloadId& Id)
|
|
{
|
|
TRACE_CPUPROFILER_EVENT_SCOPE(FDDCBackend::DoesPayloadExist);
|
|
|
|
UE::DerivedData::ICache& Cache = UE::DerivedData::GetCache();
|
|
|
|
UE::DerivedData::FCacheKey Key;
|
|
Key.Bucket = Bucket;
|
|
Key.Hash = Id.GetIdentifier();
|
|
|
|
UE::DerivedData::FRequestOwner Owner(UE::DerivedData::EPriority::Blocking);
|
|
|
|
UE::DerivedData::EStatus ResultStatus;
|
|
auto Callback = [&ResultStatus](UE::DerivedData::FCacheGetCompleteParams&& Params)
|
|
{
|
|
ResultStatus = Params.Status;
|
|
};
|
|
|
|
Cache.Get( { Key },
|
|
TEXT("Mirage"), // TODO: Improve this when we start passing more context to push
|
|
QueryPolicy | UE::DerivedData::ECachePolicy::SkipData,
|
|
Owner,
|
|
MoveTemp(Callback));
|
|
|
|
Owner.Wait();
|
|
|
|
return ResultStatus == UE::DerivedData::EStatus::Ok;
|
|
}
|
|
|
|
UE_REGISTER_VIRTUALIZATION_BACKEND_FACTORY(FDDCBackend, DDCBackend);
|
|
} // namespace UE::Virtualization
|