net.PartialBunchReliableThreshold

net.PartialBunchReliableThreshold

#Overview

name: net.PartialBunchReliableThreshold

This variable is created as a Console Variable (cvar).

It is referenced in 4 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of net.PartialBunchReliableThreshold is to control the reliability of network packet transmission in Unreal Engine’s networking system. It determines when to switch from unreliable to reliable transmission for partial bunches of data.

This setting variable is primarily used by the networking subsystem of Unreal Engine, specifically in the data channel and replication modules.

The value of this variable is set through the console variable system. It’s initialized with a default value of 8 and can be modified at runtime.

GCVarNetPartialBunchReliableThreshold is the associated variable that directly interacts with net.PartialBunchReliableThreshold. They share the same value and are used interchangeably in the code.

Developers must be aware that:

  1. This variable affects network performance and reliability.
  2. Setting it too low might unnecessarily increase network traffic and overhead.
  3. Setting it too high might result in data loss if partial bunches fail to transmit.

Best practices when using this variable include:

  1. Carefully consider the trade-off between reliability and performance when adjusting this value.
  2. Monitor network performance and adjust as needed based on your game’s specific requirements.
  3. Test thoroughly with different values to find the optimal setting for your game.

Regarding GCVarNetPartialBunchReliableThreshold: This is the internal C++ variable that stores the value of net.PartialBunchReliableThreshold. It’s used in the actual logic of the networking code to determine when to switch to reliable transmission. The same considerations and best practices apply to this variable as they do to net.PartialBunchReliableThreshold, as they are essentially the same thing, just accessed in different ways (console variable vs. C++ variable).

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/DataChannel.cpp:85

Scope: file

Source code excerpt:

int32 GCVarNetPartialBunchReliableThreshold = 8;
FAutoConsoleVariableRef CVarNetPartialBunchReliableThreshold(
	TEXT("net.PartialBunchReliableThreshold"),
	GCVarNetPartialBunchReliableThreshold,
	TEXT("If a bunch is broken up into this many partial bunches are more, we will send it reliable even if the original bunch was not reliable. Partial bunches are atonmic and must all make it over to be used"));

int32 GSkipReplicatorForDestructionInfos = 1;
FAutoConsoleVariableRef CVarNetSkipReplicatorForDestructionInfos(
	TEXT("net.SkipReplicatorForDestructionInfos"),

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/Net/RepLayout.h:1142

Scope: file

Source code excerpt:

 * alongside with other sent properties.
 *
 * When "net.PartialBunchReliableThreshold" is non-zero and property data bunches are split into partial bunches above
 * the threshold, we will not generate a history item. Instead, we will rely on the reliable bunch framework for resends
 * and replication of the Object will be completely paused until the property bunches are acknowledged.
 * However, this will not affect other history items since they are still unreliable.
 */
class FRepLayout : public FGCObject, public TSharedFromThis<FRepLayout>
{
private:

	friend struct FRepStateStaticBuffer;
	friend class UPackageMapClient;
	friend class FNetSerializeCB;
	friend struct FCustomDeltaPropertyIterator;

	FRepLayout();

public:

	virtual ~FRepLayout();

	/** Creates a new FRepLayout for the given class. */
	ENGINE_API static TSharedPtr<FRepLayout> CreateFromClass(UClass* InObjectClass, const UNetConnection* ServerConnection = nullptr, const ECreateRepLayoutFlags Flags = ECreateRepLayoutFlags::None);

	/** Creates a new FRepLayout for the given struct. */
	ENGINE_API static TSharedPtr<FRepLayout> CreateFromStruct(UStruct * InStruct, const UNetConnection* ServerConnection = nullptr, const ECreateRepLayoutFlags Flags = ECreateRepLayoutFlags::None);

	/** Creates a new FRepLayout for the given function. */
	static TSharedPtr<FRepLayout> CreateFromFunction(UFunction* InFunction, const UNetConnection* ServerConnection = nullptr, const ECreateRepLayoutFlags Flags = ECreateRepLayoutFlags::None);

	/**
	 * Creates and initialize a new Shadow Buffer.
	 *
	 * Shadow Data / Shadow States are used to cache property data so that the Object's state can be
	 * compared between frames to see if any properties have changed. They are also used on clients
	 * to keep track of RepNotify state.
	 *
	 * This includes:
	 *		- Allocating memory for all Properties in the class.
	 *		- Constructing instances of each Property.
	 *		- Copying the values of the Properties from given object.
	 *
	 * @param Source	Memory buffer storing object property data.
	 */
	FRepStateStaticBuffer CreateShadowBuffer(const FConstRepObjectDataBuffer Source) const;

	/**
	 * Creates and initializes a new FReplicationChangelistMgr.
	 *
	 * @param InObject		The Object that is being managed.
	 * @param CreateFlags	Flags modifying how the manager is created.
	 */
	TSharedPtr<FReplicationChangelistMgr> CreateReplicationChangelistMgr(const UObject* InObject, const ECreateReplicationChangelistMgrFlags CreateFlags) const;

	/**
	 * Creates and initializes a new FRepState.
	 *
	 * This includes:
	 *		- Initializing the ShadowData.
	 *		- Associating and validating the appropriate ChangedPropertyTracker.
	 *		- Building initial ConditionMap.
	 *
	 * @param RepState						The RepState to initialize.
	 * @param Class							The class of the object represented by the input memory.
	 * @param Src							Memory buffer storing object property data.
	 * @param InRepChangedPropertyTracker	The PropertyTracker we want to associate with the RepState.
	 *
	 * @return A new RepState.
	 *			Note, maybe a a FRepStateBase or FRepStateSending based on parameters.
	 */
	TUniquePtr<FRepState> CreateRepState(
		const FConstRepObjectDataBuffer Source,
		TSharedPtr<FRepChangedPropertyTracker>& InRepChangedPropertyTracker,
		ECreateRepStateFlags Flags) const;

	UE_DEPRECATED(5.1, "No longer used, trackers are initialized by the replication subsystem.")
	void InitChangedTracker(FRepChangedPropertyTracker * ChangedTracker) const;

	/**
	 * Writes out any changed properties for an Object into the given data buffer,
	 * and does book keeping for the RepState of the object.
	 *
	 * Note, this does not compare properties or send them on the wire, it's only used
	 * to serialize properties.
	 *
	 * @param RepState				RepState for the object.
	 *								This is expected to be valid.
	 * @param RepChangelistState	RepChangelistState for the object.
	 * @param Data					Pointer to memory where property data is stored.
	 * @param ObjectClass			Class of the object.
	 * @param Writer				Writer used to store / write out the replicated properties.
	 * @param RepFlags				Flags used for replication.
	 */
	bool ReplicateProperties(
		FSendingRepState* RESTRICT RepState,

#Associated Variable and Callsites

This variable is associated with another variable named GCVarNetPartialBunchReliableThreshold. They share the same value. See the following C++ source code.

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/DataChannel.cpp:83

Scope: file

Source code excerpt:

	TEXT("Time threshold for processing queued bunches during instant replays. If it takes longer than this in a single frame, wait until the next frame to continue processing queued bunches. For unlimited time, set to 0."));

int32 GCVarNetPartialBunchReliableThreshold = 8;
FAutoConsoleVariableRef CVarNetPartialBunchReliableThreshold(
	TEXT("net.PartialBunchReliableThreshold"),
	GCVarNetPartialBunchReliableThreshold,
	TEXT("If a bunch is broken up into this many partial bunches are more, we will send it reliable even if the original bunch was not reliable. Partial bunches are atonmic and must all make it over to be used"));

int32 GSkipReplicatorForDestructionInfos = 1;
FAutoConsoleVariableRef CVarNetSkipReplicatorForDestructionInfos(
	TEXT("net.SkipReplicatorForDestructionInfos"),
	GSkipReplicatorForDestructionInfos,

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/DataChannel.cpp:1326

Scope (from outer to inner):

file
function     FPacketIdRange UChannel::SendBunch

Source code excerpt:

	const bool bOverflowsReliable = (NumOutRec + OutgoingBunches.Num() >= RELIABLE_BUFFER + Bunch->bClose);

	if ((GCVarNetPartialBunchReliableThreshold > 0) && (OutgoingBunches.Num() >= GCVarNetPartialBunchReliableThreshold) && !Connection->IsInternalAck())
	{
		if (!bOverflowsReliable)
		{
			UE_LOG(LogNetPartialBunch, Log, TEXT("	OutgoingBunches.Num (%d) exceeds reliable threashold (%d). Making bunches reliable. Property replication will be paused on this channel until these are ACK'd."), OutgoingBunches.Num(), GCVarNetPartialBunchReliableThreshold);
			Bunch->bReliable = true;
			bPausedUntilReliableACK = true;
		}
		else
		{
			// The threshold was hit, but making these reliable would overflow the reliable buffer. This is a problem: there is just too much data.
			UE_LOG(LogNetPartialBunch, Warning, TEXT("	OutgoingBunches.Num (%d) exceeds reliable threashold (%d) but this would overflow the reliable buffer! Consider sending less stuff. Channel: %s"), OutgoingBunches.Num(), GCVarNetPartialBunchReliableThreshold, *Describe());
		}
	}

	if (Bunch->bReliable && bOverflowsReliable)
	{
		UE_LOG(LogNetPartialBunch, Warning, TEXT("SendBunch: Reliable partial bunch overflows reliable buffer! %s"), *Describe() );