PackagesPerGC

PackagesPerGC

#Overview

name: PackagesPerGC

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 9 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of PackagesPerGC is to control the frequency of garbage collection during the cooking process in Unreal Engine 5. It determines the number of packages that can be loaded before triggering a garbage collection operation.

This setting variable is primarily used by the CookOnTheFlyServer subsystem, which is part of the UnrealEd module. The CookOnTheFlyServer is responsible for cooking content on-demand, typically for networked games or live content updates.

The value of PackagesPerGC is set in the CookSettings section of the GEditorIni configuration file. If not specified in the config file, it defaults to 500 packages.

PackagesPerGC interacts with other variables such as IdleTimeToGC and memory-related settings (e.g., MemoryMaxUsedVirtual, MemoryMaxUsedPhysical) to manage memory usage during the cooking process.

Developers should be aware that:

  1. Setting PackagesPerGC to 0 disables garbage collection based on the number of loaded packages.
  2. This setting is usually used for debugging purposes, as memory-based triggers are more commonly used for garbage collection.
  3. The actual frequency of garbage collection checks may be adjusted based on other factors, such as cook-on-the-fly mode.

Best practices when using this variable include:

  1. Use it in conjunction with other memory management settings for optimal performance.
  2. Consider the trade-off between frequent garbage collection (which can impact performance) and memory usage.
  3. Monitor the cooking process to ensure that the chosen value doesn’t lead to excessive memory usage or frequent pauses for garbage collection.
  4. For most production scenarios, rely on memory-based triggers rather than PackagesPerGC for more efficient garbage collection management.

#Setting Variables

#References In INI files

Location: <Workspace>/Engine/Config/BaseEditor.ini:350, section: [CookSettings]

#References in C++ code

#Callsites

This variable is referenced in the following C++ source code:

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Classes/CookOnTheSide/CookOnTheFlyServer.h:319

Scope (from outer to inner):

file
class        class UCookOnTheFlyServer : public UObject, public FTickableEditorObject, public FExec, public UE::Cook::ICookInfo

Source code excerpt:


	/** Number of packages to load before performing a garbage collect. Set to 0 to never GC based on number of loaded packages */
	uint32 PackagesPerGC;
	/** Amount of time that is allowed to be idle before forcing a garbage collect. Set to 0 to never force GC due to idle time */
	double IdleTimeToGC;
	/** Amount of time to wait when save and load are busy waiting on async operations before trying them again. */
	float CookProgressRetryBusyPeriodSeconds = 0.f;

	// Memory Limits for when to Collect Garbage

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/CookOnTheFlyServer.cpp:2106

Scope (from outer to inner):

file
function     TRefCountPtr<UCookOnTheFlyServer::FPollable> UCookOnTheFlyServer::CreatePollableTriggerGC

Source code excerpt:

		PeriodSeconds = FMath::Min(PeriodSeconds, 50 * SecondsPerPackage);
	}
	if (PackagesPerGC > 0)
	{
		// PackagesPerGC is usually used only to debug; max memory counts are commonly used instead
		// Since it's not commonly used, we make a concession to support it: we check on a timer rather than checking after every saved package.
		// For large values, check less frequently.
		PeriodSeconds = FMath::Min(PeriodSeconds, PackagesPerGC * SecondsPerPackage);
	}
	if (IsCookOnTheFlyMode())
	{
		PeriodSeconds = FMath::Min(PeriodSeconds, 10.f);
		IdlePeriodSeconds = FMath::Min(IdlePeriodSeconds, 0.1f);
	}

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/CookOnTheFlyServer.cpp:2134

Scope (from outer to inner):

file
function     void UCookOnTheFlyServer::PollGarbageCollection

Source code excerpt:

		return;
	}
	if (PackagesPerGC > 0 && CookedPackageCountSinceLastGC > PackagesPerGC)
	{
		// if we are waiting on things to cache then ignore the PackagesPerGC
		if (!bSaveBusy)
		{
			StackData.ResultFlags |= COSR_RequiresGC | COSR_RequiresGC_PackageCount | COSR_YieldTick;
			return;
		}
	}

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/CookOnTheFlyServer.cpp:5945

Scope (from outer to inner):

file
function     uint32 UCookOnTheFlyServer::GetPackagesPerGC

Source code excerpt:

uint32 UCookOnTheFlyServer::GetPackagesPerGC() const
{
	return PackagesPerGC;
}

uint32 UCookOnTheFlyServer::GetPackagesPerPartialGC() const
{
	return MaxNumPackagesBeforePartialGC;
}

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/CookOnTheFlyServer.cpp:6875

Scope (from outer to inner):

file
namespace    UE::Cook
function     void FInitializeConfigSettings::LoadLocal

Source code excerpt:

	GConfig->GetInt(TEXT("CookSettings"), TEXT("MaxConcurrentShaderJobs"), MaxConcurrentShaderJobs, GEditorIni);

	PackagesPerGC = 500;
	int32 ConfigPackagesPerGC = 0;
	if (GConfig->GetInt( TEXT("CookSettings"), TEXT("PackagesPerGC"), ConfigPackagesPerGC, GEditorIni ))
	{
		// Going unsigned. Make negative values 0
		PackagesPerGC = ConfigPackagesPerGC > 0 ? ConfigPackagesPerGC : 0;
	}

	IdleTimeToGC = 20.0;
	GConfig->GetDouble( TEXT("CookSettings"), TEXT("IdleTimeToGC"), IdleTimeToGC, GEditorIni );

	auto ReadMemorySetting = [](const TCHAR* SettingName, uint64& TargetVariable)

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Cooker/CookTypes.cpp:618

Scope (from outer to inner):

file
function     FCbWriter& operator<<

Source code excerpt:

	Writer << "MaxPrecacheShaderJobs" << Value.MaxPrecacheShaderJobs;
	Writer << "MaxConcurrentShaderJobs" << Value.MaxConcurrentShaderJobs;
	Writer << "PackagesPerGC" << Value.PackagesPerGC;
	Writer << "MemoryExpectedFreedToSpreadRatio" << Value.MemoryExpectedFreedToSpreadRatio;
	Writer << "IdleTimeToGC" << Value.IdleTimeToGC;
	Writer << "MemoryMaxUsedVirtual" << Value.MemoryMaxUsedVirtual;
	Writer << "MemoryMaxUsedPhysical" << Value.MemoryMaxUsedPhysical;
	Writer << "MemoryMinFreeVirtual" << Value.MemoryMinFreeVirtual;
	Writer << "MemoryMinFreePhysical" << Value.MemoryMinFreePhysical;

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Cooker/CookTypes.cpp:644

Scope (from outer to inner):

file
function     bool LoadFromCompactBinary

Source code excerpt:

	bOk = LoadFromCompactBinary(Field["MaxPrecacheShaderJobs"], OutValue.MaxPrecacheShaderJobs) & bOk;
	bOk = LoadFromCompactBinary(Field["MaxConcurrentShaderJobs"], OutValue.MaxConcurrentShaderJobs) & bOk;
	bOk = LoadFromCompactBinary(Field["PackagesPerGC"], OutValue.PackagesPerGC) & bOk;
	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;

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Cooker/CookTypes.cpp:681

Scope (from outer to inner):

file
namespace    UE::Cook
function     void FInitializeConfigSettings::MoveOrCopy

Source code excerpt:

	Target.MaxPrecacheShaderJobs = Source.MaxPrecacheShaderJobs;
	Target.MaxConcurrentShaderJobs = Source.MaxConcurrentShaderJobs;
	Target.PackagesPerGC = Source.PackagesPerGC;
	Target.MemoryExpectedFreedToSpreadRatio = Source.MemoryExpectedFreedToSpreadRatio;
	Target.IdleTimeToGC = Source.IdleTimeToGC;
	Target.MemoryMaxUsedVirtual = Source.MemoryMaxUsedVirtual;
	Target.MemoryMaxUsedPhysical = Source.MemoryMaxUsedPhysical;
	Target.MemoryMinFreeVirtual = Source.MemoryMinFreeVirtual;
	Target.MemoryMinFreePhysical = Source.MemoryMinFreePhysical;

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Cooker/CookTypes.h:313

Scope (from outer to inner):

file
namespace    UE::Cook

Source code excerpt:

		int32 MaxPrecacheShaderJobs = 0;
		int32 MaxConcurrentShaderJobs = 0;
		uint32 PackagesPerGC = 0;
		float MemoryExpectedFreedToSpreadRatio = 0.f;
		double IdleTimeToGC = 0.;
		uint64 MemoryMaxUsedVirtual;
		uint64 MemoryMaxUsedPhysical;
		uint64 MemoryMinFreeVirtual;
		uint64 MemoryMinFreePhysical;