net.IpConnectionUseSendTasks

net.IpConnectionUseSendTasks

#Overview

name: net.IpConnectionUseSendTasks

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

It is referenced in 8 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of net.IpConnectionUseSendTasks is to control whether the IpConnection will call the socket’s SendTo function in a task graph task, allowing it to run off the game thread. This setting is primarily used for networking optimization in Unreal Engine.

This setting variable is primarily used in the OnlineSubsystemUtils module, specifically within the IpConnection class. It affects how network data is sent over IP connections.

The value of this variable is set through a console variable (CVarNetIpConnectionUseSendTasks) defined in IpConnection.cpp. It defaults to 0 (false) but can be changed at runtime.

The associated variable CVarNetIpConnectionUseSendTasks directly interacts with net.IpConnectionUseSendTasks. They share the same value and are used interchangeably in the code.

Developers must be aware that enabling this setting (setting it to non-zero) will change the behavior of how network data is sent. It will use task graph tasks for sending data, which can improve performance by offloading work from the game thread but may also introduce additional complexity in debugging and synchronization.

Best practices when using this variable include:

  1. Test thoroughly with both enabled and disabled states to ensure your game performs well in both scenarios.
  2. Monitor performance metrics to determine if enabling this feature provides a significant benefit for your specific use case.
  3. Be cautious when enabling this in production, as it changes the threading model for network operations.

Regarding the associated variable CVarNetIpConnectionUseSendTasks:

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Plugins/Online/OnlineSubsystemUtils/Source/OnlineSubsystemUtils/Private/IpConnection.cpp:36

Scope: file

Source code excerpt:


TAutoConsoleVariable<int32> CVarNetIpConnectionUseSendTasks(
	TEXT("net.IpConnectionUseSendTasks"),
	0,
	TEXT("If true, the IpConnection will call the socket's SendTo function in a task graph task so that it can run off the game thread."));

TAutoConsoleVariable<int32> CVarNetIpConnectionDisableResolution(
	TEXT("net.IpConnectionDisableResolution"),
	0,

#Loc: <Workspace>/Engine/Plugins/Online/OnlineSubsystemUtils/Source/OnlineSubsystemUtils/Classes/IpConnection.h:87

Scope (from outer to inner):

file
function     class ONLINESUBSYSTEMUTILS_API UIpConnection : public UNetConnection { GENERATED_UCLASS_BODY

Source code excerpt:

private:
	/**
	 * Struct to hold the result of a socket SendTo call. If net.IpConnectionUseSendTasks is true,
	 * these are communicated back to the game thread via SocketSendResults.
	 */
	struct FSocketSendResult
	{
		int32 BytesSent = 0;
		ESocketErrors Error = SE_NO_ERROR;
	};

	/** Critical section to protect SocketSendResults */
	FCriticalSection SocketSendResultsCriticalSection;

	/** Socket SendTo results from send tasks if net.IpConnectionUseSendTasks is true */
	TArray<FSocketSendResult> SocketSendResults;

	/**
	 * If net.IpConnectionUseSendTasks is true, reference to the last send task used as a prerequisite
	 * for the next send task. Also, CleanUp() blocks until this task is complete.
	 */
	FGraphEventRef LastSendTask;

	/** The socket used for communication (typically shared between NetConnection's, Net Address Resolution, and the NetDriver) */
	TSharedPtr<FSocket> SocketPrivate;

	/** List of previously active sockets for this connection, whose cleanup is deferred for multithreaded safety and to prevent remote ICMP errors */
	TArray<TSharedPtr<FSocket>> DeferredCleanupSockets;

#Associated Variable and Callsites

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

#Loc: <Workspace>/Engine/Plugins/Online/OnlineSubsystemUtils/Source/OnlineSubsystemUtils/Classes/IpConnection.h:63

Scope (from outer to inner):

file
function     class ONLINESUBSYSTEMUTILS_API UIpConnection : public UNetConnection { GENERATED_UCLASS_BODY

Source code excerpt:


	/**
	 * If CVarNetIpConnectionUseSendTasks is true, blocks until there are no outstanding send tasks.
	 * Since these tasks need to access the socket, this is called before the net driver closes the socket.
	 */
	void WaitForSendTasks();

	/**
	 * Gets the cached socket for this connection.
	 *
	 * @return	The cached socket for this connection
	 */

#Loc: <Workspace>/Engine/Plugins/Online/OnlineSubsystemUtils/Source/OnlineSubsystemUtils/Private/IpConnection.cpp:35

Scope: file

Source code excerpt:

DECLARE_CYCLE_STAT(TEXT("IpConnection WaitForSendTasks"), STAT_IpConnection_WaitForSendTasks, STATGROUP_Net);

TAutoConsoleVariable<int32> CVarNetIpConnectionUseSendTasks(
	TEXT("net.IpConnectionUseSendTasks"),
	0,
	TEXT("If true, the IpConnection will call the socket's SendTo function in a task graph task so that it can run off the game thread."));

TAutoConsoleVariable<int32> CVarNetIpConnectionDisableResolution(
	TEXT("net.IpConnectionDisableResolution"),

#Loc: <Workspace>/Engine/Plugins/Online/OnlineSubsystemUtils/Source/OnlineSubsystemUtils/Private/IpConnection.cpp:182

Scope (from outer to inner):

file
function     void UIpConnection::Tick

Source code excerpt:

	using namespace UE::Net::Private;

	if (CVarNetIpConnectionUseSendTasks.GetValueOnGameThread() != 0)
	{
		ISocketSubsystem* const SocketSubsystem = Driver->GetSocketSubsystem();
		TArray<FSocketSendResult> ResultsCopy;

		{
			FScopeLock ScopeLock(&SocketSendResultsCriticalSection);

#Loc: <Workspace>/Engine/Plugins/Online/OnlineSubsystemUtils/Source/OnlineSubsystemUtils/Private/IpConnection.cpp:363

Scope (from outer to inner):

file
function     void UIpConnection::SafeDeferredSocketCleanup

Source code excerpt:

		DeferredCleanupTimeCheck = LastReceiveRealtime;

		if (CVarNetIpConnectionUseSendTasks.GetValueOnGameThread() != 0 && LastSendTask.IsValid())
		{
			DECLARE_CYCLE_STAT(TEXT("IpConnection SocketCleanup task"), STAT_IpConnection_SocketCleanupTask, STATGROUP_TaskGraphTasks);

			FGraphEventArray Prerequisites;

			Prerequisites.Add(LastSendTask);

#Loc: <Workspace>/Engine/Plugins/Online/OnlineSubsystemUtils/Source/OnlineSubsystemUtils/Private/IpConnection.cpp:402

Scope (from outer to inner):

file
function     void UIpConnection::WaitForSendTasks

Source code excerpt:

void UIpConnection::WaitForSendTasks()
{
	if (CVarNetIpConnectionUseSendTasks.GetValueOnGameThread() != 0 && LastSendTask.IsValid())
	{
		check(IsInGameThread());

		SCOPE_CYCLE_COUNTER(STAT_IpConnection_WaitForSendTasks);
		FTaskGraphInterface::Get().WaitUntilTaskCompletes(LastSendTask, ENamedThreads::GameThread);

#Loc: <Workspace>/Engine/Plugins/Online/OnlineSubsystemUtils/Source/OnlineSubsystemUtils/Private/IpConnection.cpp:501

Scope (from outer to inner):

file
function     void UIpConnection::LowLevelSend

Source code excerpt:

			FSocket* CurSocket = GetSocket();

			if (CVarNetIpConnectionUseSendTasks.GetValueOnAnyThread() != 0)
			{
				DECLARE_CYCLE_STAT(TEXT("IpConnection SendTo task"), STAT_IpConnection_SendToTask, STATGROUP_TaskGraphTasks);

				FGraphEventArray Prerequisites;
				if (LastSendTask.IsValid())
				{