MemoryMaxUsedVirtual
MemoryMaxUsedVirtual
#Overview
name: MemoryMaxUsedVirtual
The value of this variable can be defined or overridden in .ini config files. 1
.ini config file referencing this setting variable.
It is referenced in 14
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of MemoryMaxUsedVirtual is to set a maximum limit for virtual memory usage during the cooking process in Unreal Engine 5. It is primarily used as a threshold to trigger garbage collection and manage memory usage in the editor and cooking tools.
This setting variable is relied upon by the following Unreal Engine subsystems and modules:
- NaniteDisplacedMeshEditor plugin
- CookOnTheFlyServer in the UnrealEd module
- CookDirector in the UnrealEd module
The value of this variable is typically set in the GEditorIni configuration file under the [CookSettings] section. It can be loaded and modified programmatically, as seen in the UGenerateNaniteDisplacedMeshCommandlet and UCookOnTheFlyServer classes.
MemoryMaxUsedVirtual interacts with several other memory-related variables, such as:
- MemoryMaxUsedPhysical
- MemoryMinFreeVirtual
- MemoryMinFreePhysical
- MemoryTriggerGCAtPressureLevel
Developers must be aware of the following when using this variable:
- The value is specified in bytes, but it’s often set using megabytes (MB) and then converted to bytes in the code.
- Setting this value too low may cause frequent garbage collection, potentially slowing down the cooking process.
- Setting it too high may lead to excessive memory usage and potential system instability.
Best practices when using this variable include:
- Set a reasonable value based on the available system resources and the project’s requirements.
- Monitor memory usage during cooking to fine-tune this setting.
- Consider the interaction with other memory-related settings to achieve optimal performance and stability.
- Ensure that the value doesn’t exceed the total available physical memory on the system to prevent unintended behavior.
- Use in conjunction with other memory management settings for a comprehensive memory management strategy during cooking.
#Setting Variables
#References In INI files
Location: <Workspace>/Engine/Config/BaseEditor.ini:363, section: [CookSettings]
- INI Section:
CookSettings
- Raw value:
0
- Is Array:
False
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Plugins/Experimental/NaniteDisplacedMesh/Source/NaniteDisplacedMeshEditor/Private/GenerateNaniteDisplacedMeshCommandlet.cpp:134
Scope (from outer to inner):
file
function int32 UGenerateNaniteDisplacedMeshCommandlet::Main
Source code excerpt:
}
if (GConfig->GetInt(TEXT("CookSettings"), TEXT("MemoryMaxUsedVirtual"), ValueInMB, GEditorIni))
{
ValueInMB = FMath::Max(ValueInMB, 0);
MemoryMaxUsedVirtual = ValueInMB * 1024ULL * 1024ULL;
UE_LOG(LogNaniteDisplacedMesh, Display, TEXT("Loaded MemoryMaxUsedVirtual from CookSettings (%d MiB)"), ValueInMB);
}
if (GConfig->GetInt(TEXT("CookSettings"), TEXT("MemoryMinFreePhysical"), ValueInMB, GEditorIni))
{
ValueInMB = FMath::Max(ValueInMB, 0);
#Loc: <Workspace>/Engine/Plugins/Experimental/NaniteDisplacedMesh/Source/NaniteDisplacedMeshEditor/Private/GenerateNaniteDisplacedMeshCommandlet.cpp:551
Scope (from outer to inner):
file
function void UGenerateNaniteDisplacedMeshCommandlet::LoadLevel
lambda-function
Source code excerpt:
}
if (MemoryMaxUsedVirtual > 0 && MemoryStats.UsedVirtual > MemoryMaxUsedVirtual)
{
UE_LOG(LogNaniteDisplacedMesh, Display, TEXT("High virtual memory usage (%d MiB). kicking GC."), MemoryStats.UsedVirtual / 1024 / 1024);
return true;
}
if (MemoryMaxUsedPhysical > 0 && MemoryStats.UsedPhysical > MemoryMaxUsedPhysical)
#Loc: <Workspace>/Engine/Plugins/Experimental/NaniteDisplacedMesh/Source/NaniteDisplacedMeshEditor/Private/GenerateNaniteDisplacedMeshCommandlet.h:48
Scope (from outer to inner):
file
class class UGenerateNaniteDisplacedMeshCommandlet : public UCommandlet
Source code excerpt:
// Soft limit for when the garbage collector should be kicked (it use the same settings as the cook and will load these if found)
uint64 MemoryMinFreeVirtual = 8192;
uint64 MemoryMaxUsedVirtual= 98304;
uint64 MemoryMinFreePhysical= 8192;
uint64 MemoryMaxUsedPhysical= 0;
struct FOnLinkDisplacedMeshArgs
{
FNaniteDisplacedMeshParams Parameters;
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Classes/CookOnTheSide/CookOnTheFlyServer.h:326
Scope (from outer to inner):
file
class class UCookOnTheFlyServer : public UObject, public FTickableEditorObject, public FExec, public UE::Cook::ICookInfo
Source code excerpt:
// Memory Limits for when to Collect Garbage
uint64 MemoryMaxUsedVirtual;
uint64 MemoryMaxUsedPhysical;
uint64 MemoryMinFreeVirtual;
uint64 MemoryMinFreePhysical;
FGenericPlatformMemoryStats::EMemoryPressureStatus MemoryTriggerGCAtPressureLevel;
float MemoryExpectedFreedToSpreadRatio;
/** Max number of packages to save before we partial gc */
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/CookOnTheFlyServer.cpp:4976
Scope (from outer to inner):
file
function bool UCookOnTheFlyServer::PumpHasExceededMaxMemory
Source code excerpt:
// this can be useful if you demand that amount of memory as your min spec
bool bMaxUsedTriggered = false;
if (MemoryMaxUsedVirtual > 0 || MemoryMaxUsedPhysical > 0)
{
// check validity of trigger :
// if the MaxUsed config exceeds the system memory, it can never be triggered and will prevent any GC :
uint64 MaxMaxUsed = FMath::Max(MemoryMaxUsedVirtual,MemoryMaxUsedPhysical);
if (MaxMaxUsed >= MemStats.TotalPhysical)
{
UE_CALL_ONCE([&]() {
UE_LOG(LogCook, Warning, TEXT("Warning MemoryMaxUsed condition is larger than total memory (%dMiB >= %dMiB). System does not have enough memory to cook this project."),
static_cast<uint32>(MaxMaxUsed / 1024 / 1024), static_cast<uint32>(MemStats.TotalPhysical / 1024 / 1024));
});
}
if (MemoryMaxUsedVirtual > 0 && MemStats.UsedVirtual >= MemoryMaxUsedVirtual)
{
TriggerMessages.Appendf(TEXT("\n CookSettings.MemoryMaxUsedVirtual: Used virtual memory %dMiB is greater than %dMiB."),
static_cast<uint32>(MemStats.UsedVirtual / 1024 / 1024), static_cast<uint32>(MemoryMaxUsedVirtual / 1024 / 1024));
bMaxUsedTriggered = true;
}
if (MemoryMaxUsedPhysical > 0 && MemStats.UsedPhysical >= MemoryMaxUsedPhysical)
{
TriggerMessages.Appendf(TEXT("\n CookSettings.MemoryMaxUsedPhysical: Used physical memory %dMiB is greater than %dMiB."),
static_cast<uint32>(MemStats.UsedPhysical / 1024 / 1024), static_cast<uint32>(MemoryMaxUsedPhysical / 1024 / 1024));
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/CookOnTheFlyServer.cpp:5034
Scope (from outer to inner):
file
function bool UCookOnTheFlyServer::PumpHasExceededMaxMemory
Source code excerpt:
if (!bOnlyTriggerIfBothMinFreeAndMaxUsedTrigger ||
((bMinFreeTriggered || (MemoryMinFreeVirtual <= 0 && MemoryMinFreePhysical <= 0)) &&
(bMaxUsedTriggered || (MemoryMaxUsedVirtual <= 0 && MemoryMaxUsedPhysical <= 0))))
{
bTriggerGC = true;
}
}
if (bPressureTriggered)
{
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/CookOnTheFlyServer.cpp:6897
Scope (from outer to inner):
file
namespace UE::Cook
function void FInitializeConfigSettings::LoadLocal
Source code excerpt:
return false;
};
MemoryMaxUsedVirtual = 0;
MemoryMaxUsedPhysical = 0;
MemoryMinFreeVirtual = 0;
MemoryMinFreePhysical = 0;
bUseSoftGC = false;
SoftGCStartNumerator = 5;
SoftGCDenominator = 10;
ReadMemorySetting(TEXT("MemoryMaxUsedVirtual"), MemoryMaxUsedVirtual);
ReadMemorySetting(TEXT("MemoryMaxUsedPhysical"), MemoryMaxUsedPhysical);
ReadMemorySetting(TEXT("MemoryMinFreeVirtual"), MemoryMinFreeVirtual);
ReadMemorySetting(TEXT("MemoryMinFreePhysical"), MemoryMinFreePhysical);
FString ConfigText(TEXT("None"));
GConfig->GetString(TEXT("CookSettings"), TEXT("MemoryTriggerGCAtPressureLevel"), ConfigText, GEditorIni);
if (!LexTryParseString(MemoryTriggerGCAtPressureLevel, ConfigText))
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/CookOnTheFlyServer.cpp:6940
Scope (from outer to inner):
file
namespace UE::Cook
function void FInitializeConfigSettings::LoadLocal
Source code excerpt:
TEXT("\n\tMemoryTriggerGCAtPressureLevel %s")
TEXT("\n\tUseSoftGC %s%s"),
MemoryMaxUsedVirtual / 1024 / 1024, MemoryMaxUsedPhysical / 1024 / 1024, MemoryMinFreeVirtual / 1024 / 1024, MemoryMinFreePhysical / 1024 / 1024,
*LexToString(MemoryTriggerGCAtPressureLevel),
bUseSoftGC ? TEXT("true") : TEXT("false"),
bUseSoftGC ? *FString::Printf(TEXT(" (%d/%d)"), SoftGCStartNumerator, SoftGCDenominator) : TEXT(""));
const FConfigSection* CacheSettings = GConfig->GetSection(TEXT("CookPlatformDataCacheSettings"), false, GEditorIni);
if (CacheSettings)
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Cooker/CookDirector.cpp:1065
Scope (from outer to inner):
file
namespace UE::Cook
function void FCookDirector::ActivateMachineResourceReduction
Source code excerpt:
// When running a multiprocess cook, we remove the Memory triggers and trigger GC based solely on PressureLevel. But keep the Soft GC settings
COTFS.MemoryMaxUsedPhysical = 0;
COTFS.MemoryMaxUsedVirtual = 0;
COTFS.MemoryMinFreeVirtual = 0;
COTFS.MemoryMinFreePhysical = 0;
COTFS.MemoryTriggerGCAtPressureLevel = FGenericPlatformMemoryStats::EMemoryPressureStatus::Critical;
UE_LOG(LogCook, Display, TEXT("CookMultiprocess changed CookSettings for Memory:")
TEXT("\n\tMemoryMaxUsedVirtual %dMiB")
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Cooker/CookDirector.cpp:1077
Scope (from outer to inner):
file
namespace UE::Cook
function void FCookDirector::ActivateMachineResourceReduction
Source code excerpt:
TEXT("\n\tMemoryTriggerGCAtPressureLevel %s")
TEXT("\n\tUseSoftGC %s%s"),
COTFS.MemoryMaxUsedVirtual / 1024 / 1024, COTFS.MemoryMaxUsedPhysical / 1024 / 1024,
COTFS.MemoryMinFreeVirtual / 1024 / 1024, COTFS.MemoryMinFreePhysical / 1024 / 1024,
*LexToString(COTFS.MemoryTriggerGCAtPressureLevel),
COTFS.bUseSoftGC ? TEXT("true") : TEXT("false"),
COTFS.bUseSoftGC ? *FString::Printf(TEXT(" (%d/%d)"), COTFS.SoftGCStartNumerator, COTFS.SoftGCDenominator) : TEXT("")
);
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Cooker/CookTypes.cpp:621
Scope (from outer to inner):
file
function FCbWriter& operator<<
Source code excerpt:
Writer << "MemoryExpectedFreedToSpreadRatio" << Value.MemoryExpectedFreedToSpreadRatio;
Writer << "IdleTimeToGC" << Value.IdleTimeToGC;
Writer << "MemoryMaxUsedVirtual" << Value.MemoryMaxUsedVirtual;
Writer << "MemoryMaxUsedPhysical" << Value.MemoryMaxUsedPhysical;
Writer << "MemoryMinFreeVirtual" << Value.MemoryMinFreeVirtual;
Writer << "MemoryMinFreePhysical" << Value.MemoryMinFreePhysical;
Writer << "MemoryTriggerGCAtPressureLevel" << static_cast<uint8>(Value.MemoryTriggerGCAtPressureLevel);
Writer << "bUseSoftGC" << Value.bUseSoftGC;
Writer << "SoftGCStartNumerator" << Value.SoftGCStartNumerator;
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Cooker/CookTypes.cpp:647
Scope (from outer to inner):
file
function bool LoadFromCompactBinary
Source code excerpt:
bOk = LoadFromCompactBinary(Field["MemoryExpectedFreedToSpreadRatio"], OutValue.MemoryExpectedFreedToSpreadRatio) & bOk;
bOk = LoadFromCompactBinary(Field["IdleTimeToGC"], OutValue.IdleTimeToGC) & bOk;
bOk = LoadFromCompactBinary(Field["MemoryMaxUsedVirtual"], OutValue.MemoryMaxUsedVirtual) & bOk;
bOk = LoadFromCompactBinary(Field["MemoryMaxUsedPhysical"], OutValue.MemoryMaxUsedPhysical) & bOk;
bOk = LoadFromCompactBinary(Field["MemoryMinFreeVirtual"], OutValue.MemoryMinFreeVirtual) & bOk;
bOk = LoadFromCompactBinary(Field["MemoryMinFreePhysical"], OutValue.MemoryMinFreePhysical) & bOk;
uint8 PressureLevelAsInt;
if (LoadFromCompactBinary(Field["MemoryTriggerGCAtPressureLevel"], PressureLevelAsInt))
{
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Cooker/CookTypes.cpp:684
Scope (from outer to inner):
file
namespace UE::Cook
function void FInitializeConfigSettings::MoveOrCopy
Source code excerpt:
Target.MemoryExpectedFreedToSpreadRatio = Source.MemoryExpectedFreedToSpreadRatio;
Target.IdleTimeToGC = Source.IdleTimeToGC;
Target.MemoryMaxUsedVirtual = Source.MemoryMaxUsedVirtual;
Target.MemoryMaxUsedPhysical = Source.MemoryMaxUsedPhysical;
Target.MemoryMinFreeVirtual = Source.MemoryMinFreeVirtual;
Target.MemoryMinFreePhysical = Source.MemoryMinFreePhysical;
Target.MemoryTriggerGCAtPressureLevel = Source.MemoryTriggerGCAtPressureLevel;
Target.bUseSoftGC = Source.bUseSoftGC;
Target.SoftGCStartNumerator = Source.SoftGCStartNumerator;
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Cooker/CookTypes.h:316
Scope (from outer to inner):
file
namespace UE::Cook
Source code excerpt:
float MemoryExpectedFreedToSpreadRatio = 0.f;
double IdleTimeToGC = 0.;
uint64 MemoryMaxUsedVirtual;
uint64 MemoryMaxUsedPhysical;
uint64 MemoryMinFreeVirtual;
uint64 MemoryMinFreePhysical;
FGenericPlatformMemoryStats::EMemoryPressureStatus MemoryTriggerGCAtPressureLevel;
int32 MinFreeUObjectIndicesBeforeGC;
int32 MaxNumPackagesBeforePartialGC;