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:

  1. Cook-on-the-fly system (CookOnTheFlyServer)
  2. Nanite Displaced Mesh generation
  3. 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:

Developers should be aware of the following when using this variable:

  1. Setting it too low may cause frequent garbage collection, impacting performance.
  2. Setting it too high may lead to excessive memory usage and potential system instability.
  3. 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:

  1. Set it based on the target hardware specifications and the specific needs of your project.
  2. Consider the relationship between this variable and other memory-related settings to achieve optimal performance and stability.
  3. Monitor memory usage during development and adjust the value as needed.
  4. 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]

#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()