MemoryMaxUsedPhysical
MemoryMaxUsedPhysical
#Overview
name: MemoryMaxUsedPhysical
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 16
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of MemoryMaxUsedPhysical is to set an upper limit on the amount of physical memory that can be used by the Unreal Engine process before triggering certain actions, such as garbage collection or memory management operations.
This setting variable is primarily used in the following Unreal Engine subsystems and modules:
- Cook-on-the-fly system (CookOnTheFlyServer)
- Nanite Displaced Mesh generation
- World Partition system
The value of this variable is typically set in the configuration files, specifically in the “CookSettings” section of the GEditorIni file. It can be loaded and modified programmatically as well.
MemoryMaxUsedPhysical often interacts with other memory-related variables such as:
- MemoryMaxUsedVirtual
- MemoryMinFreePhysical
- MemoryMinFreeVirtual
- MemoryTriggerGCAtPressureLevel
Developers should be aware of the following when using this variable:
- Setting it too low may cause frequent garbage collection, impacting performance.
- Setting it too high may lead to excessive memory usage and potential system instability.
- It’s used in conjunction with other memory thresholds to determine when to trigger garbage collection or other memory management actions.
Best practices for using this variable include:
- Set it based on the target hardware specifications and the specific needs of your project.
- Consider the relationship between this variable and other memory-related settings to achieve optimal performance and stability.
- Monitor memory usage during development and adjust the value as needed.
- Be cautious when modifying this value, as it can significantly impact the engine’s memory management behavior.
#Setting Variables
#References In INI files
Location: <Workspace>/Engine/Config/BaseEditor.ini:362, 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:148
Scope (from outer to inner):
file
function int32 UGenerateNaniteDisplacedMeshCommandlet::Main
Source code excerpt:
}
if (GConfig->GetInt(TEXT("CookSettings"), TEXT("MemoryMaxUsedPhysical"), ValueInMB, GEditorIni))
{
ValueInMB = FMath::Max(ValueInMB, 0);
MemoryMaxUsedPhysical = ValueInMB * 1024ULL * 1024ULL;
UE_LOG(LogNaniteDisplacedMesh, Display, TEXT("Loaded MemoryMaxUsedPhysical from CookSettings (%d MiB)"), ValueInMB);
}
IAssetRegistry& AssetRegistry = FAssetRegistryModule::GetRegistry();
if (UE::AssetRegistry::ShouldSearchAllAssetsAtStart())
#Loc: <Workspace>/Engine/Plugins/Experimental/NaniteDisplacedMesh/Source/NaniteDisplacedMeshEditor/Private/GenerateNaniteDisplacedMeshCommandlet.cpp:557
Scope (from outer to inner):
file
function void UGenerateNaniteDisplacedMeshCommandlet::LoadLevel
lambda-function
Source code excerpt:
}
if (MemoryMaxUsedPhysical > 0 && MemoryStats.UsedPhysical > MemoryMaxUsedPhysical)
{
UE_LOG(LogNaniteDisplacedMesh, Display, TEXT("High physical memory usage (% dMiB). kicking GC."), MemoryStats.UsedPhysical / 1024 / 1024);
return true;
}
return false;
#Loc: <Workspace>/Engine/Plugins/Experimental/NaniteDisplacedMesh/Source/NaniteDisplacedMeshEditor/Private/GenerateNaniteDisplacedMeshCommandlet.h:50
Scope (from outer to inner):
file
class class UGenerateNaniteDisplacedMeshCommandlet : public UCommandlet
Source code excerpt:
uint64 MemoryMaxUsedVirtual= 98304;
uint64 MemoryMinFreePhysical= 8192;
uint64 MemoryMaxUsedPhysical= 0;
struct FOnLinkDisplacedMeshArgs
{
FNaniteDisplacedMeshParams Parameters;
FString Folder;
ELinkDisplacedMeshAssetSetting LinkDisplacedMeshAssetSetting;
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Classes/CookOnTheSide/CookOnTheFlyServer.h:327
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 */
int32 MaxNumPackagesBeforePartialGC;
#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));
});
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/CookOnTheFlyServer.cpp:4995
Scope (from outer to inner):
file
function bool UCookOnTheFlyServer::PumpHasExceededMaxMemory
Source code excerpt:
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));
bMaxUsedTriggered = true;
}
}
bool bPressureTriggered = false;
if (MemoryTriggerGCAtPressureLevel != FPlatformMemoryStats::EMemoryPressureStatus::Unknown)
#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:6898
Scope (from outer to inner):
file
namespace UE::Cook
function void FInitializeConfigSettings::LoadLocal
Source code excerpt:
};
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:1064
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:")
#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:622
Scope (from outer to inner):
file
function FCbWriter& operator<<
Source code excerpt:
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;
Writer << "SoftGCDenominator" << Value.SoftGCDenominator;
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Cooker/CookTypes.cpp:648
Scope (from outer to inner):
file
function bool LoadFromCompactBinary
Source code excerpt:
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))
{
OutValue.MemoryTriggerGCAtPressureLevel = static_cast<FGenericPlatformMemoryStats::EMemoryPressureStatus>(PressureLevelAsInt);
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Cooker/CookTypes.cpp:685
Scope (from outer to inner):
file
namespace UE::Cook
function void FInitializeConfigSettings::MoveOrCopy
Source code excerpt:
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;
Target.SoftGCDenominator = Source.SoftGCDenominator;
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Cooker/CookTypes.h:317
Scope (from outer to inner):
file
namespace UE::Cook
Source code excerpt:
double IdleTimeToGC = 0.;
uint64 MemoryMaxUsedVirtual;
uint64 MemoryMaxUsedPhysical;
uint64 MemoryMinFreeVirtual;
uint64 MemoryMinFreePhysical;
FGenericPlatformMemoryStats::EMemoryPressureStatus MemoryTriggerGCAtPressureLevel;
int32 MinFreeUObjectIndicesBeforeGC;
int32 MaxNumPackagesBeforePartialGC;
int32 SoftGCStartNumerator;
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/WorldPartition/WorldPartitionHelpers.cpp:239
Scope (from outer to inner):
file
function bool FWorldPartitionHelpers::HasExceededMaxMemory
Source code excerpt:
const uint64 MemoryMinFreePhysical = 1llu * 1024 * 1024 * 1024;
const uint64 MemoryMaxUsedPhysical = FMath::Max(32llu * 1024 * 1024 * 1024, MemStats.TotalPhysical / 2);
const bool bHasExceededMinFreePhysical = MemStats.AvailablePhysical < MemoryMinFreePhysical;
const bool bHasExceededMaxUsedPhysical = MemStats.UsedPhysical >= MemoryMaxUsedPhysical;
const bool bHasExceededMaxMemory = bHasExceededMinFreePhysical || bHasExceededMaxUsedPhysical;
return bHasExceededMaxMemory;
}
bool FWorldPartitionHelpers::ShouldCollectGarbage()