Improved LiteNetLib transport performance by removing two needless data copies when sending and receiving a packet.

This commit is contained in:
Karrar
2024-11-11 11:27:31 +03:00
parent a17225f16e
commit e31cb736ec
11 changed files with 31 additions and 88 deletions

View File

@@ -6,7 +6,7 @@
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Karrar Rahim")] [assembly: AssemblyCompany("Karrar Rahim")]
[assembly: AssemblyProduct("Netick")] [assembly: AssemblyProduct("Netick")]
[assembly: AssemblyCopyright("Karrar Rahim 2023")] [assembly: AssemblyCopyright("Karrar Rahim 2025")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
#endif #endif

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,13 +1,11 @@
using LiteNetLib; using LiteNetLib;
using LiteNetLib.Utils; using LiteNetLib.Utils;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System; using System;
using Netick.Unity; using Netick.Unity;
using UnityEngine.UIElements;
namespace Netick.Transport namespace Netick.Transport
{ {
@@ -22,7 +20,6 @@ namespace Netick.Transport
public int MaxConnectAttempts = 10; public int MaxConnectAttempts = 10;
[Tooltip("LiteNetLib internal logic update interval (in seconds).")] [Tooltip("LiteNetLib internal logic update interval (in seconds).")]
public float UpdateInterval = 0.015f; public float UpdateInterval = 0.015f;
public override NetworkTransport MakeTransportInstance() => new LiteNetLibTransport(this); public override NetworkTransport MakeTransportInstance() => new LiteNetLibTransport(this);
} }
@@ -33,51 +30,24 @@ namespace Netick.Transport
public LiteNetLibTransport Transport; public LiteNetLibTransport Transport;
public NetPeer LNLPeer; public NetPeer LNLPeer;
public override IEndPoint EndPoint => LNLPeer.EndPoint.ToNetickEndPoint(); public override IEndPoint EndPoint => LNLPeer.EndPoint.ToNetickEndPoint();
public override int Mtu => LNLPeer.Mtu; public override int Mtu => LNLPeer.Mtu;
public LNLConnection(LiteNetLibTransport transport) public LNLConnection(LiteNetLibTransport transport)
{ {
Transport = transport; Transport = transport;
} }
public unsafe override void Send(IntPtr ptr, int length) => LNLPeer.Send(new ReadOnlySpan<byte>(ptr.ToPointer(), length), DeliveryMethod.Unreliable);
public unsafe override void Send(IntPtr ptr, int length) public unsafe override void SendUserData(IntPtr ptr, int length, TransportDeliveryMethod method) => LNLPeer.Send(new ReadOnlySpan<byte>(ptr.ToPointer(), length), method == TransportDeliveryMethod.Unreliable ? DeliveryMethod.Unreliable : DeliveryMethod.ReliableOrdered);
{
SendLNL((byte*)ptr.ToPointer(), length, DeliveryMethod.Unreliable);
}
public unsafe override void SendUserData(IntPtr ptr, int length, TransportDeliveryMethod transportDeliveryMethod)
{
SendLNL((byte*)ptr.ToPointer(), length, transportDeliveryMethod == TransportDeliveryMethod.Reliable ? DeliveryMethod.ReliableOrdered : DeliveryMethod.Unreliable);
}
private unsafe void SendLNL(byte* ptr, int length, DeliveryMethod deliveryMethod)
{
if (Transport._bytes.Length < length)
Transport._bytes = new byte[length];
for (int i = 0; i < length; i++)
Transport._bytes[i] = ptr[i];
LNLPeer.Send(Transport._bytes, 0, length, deliveryMethod);
}
} }
private LiteNetLibTransportProvider _provider; private LiteNetLibTransportProvider _provider;
private NetManager _netManager; private NetManager _netManager;
private BitBuffer _buffer;
private byte[] _bytes = new byte[2048];
private readonly byte[] _connectionBytes = new byte[200];
private int _port;
private Dictionary<NetPeer, LNLConnection> _clients = new();
private Queue<LNLConnection> _freeClients = new();
// LAN Discovery
private List<Session> _sessions = new();
private NetDataWriter _writer = new NetDataWriter(); private NetDataWriter _writer = new NetDataWriter();
private string _machineName; private BitBuffer _buffer;
private byte[] _connectionBytes = new byte[200];
private int _port;
private Dictionary<NetPeer, LNLConnection> _clients;
private Queue<LNLConnection> _freeClients;
public LiteNetLibTransport(LiteNetLibTransportProvider provider) public LiteNetLibTransport(LiteNetLibTransportProvider provider)
{ {
this._provider = provider; this._provider = provider;
@@ -85,43 +55,36 @@ namespace Netick.Transport
public override void Init() public override void Init()
{ {
_clients = new(Engine.Config.MaxPlayers);
_freeClients = new(Engine.Config.MaxPlayers);
_buffer = new BitBuffer(createChunks: false); _buffer = new BitBuffer(createChunks: false);
_netManager = new NetManager((INetEventListener)this) { AutoRecycle = true }; _netManager = new NetManager(this) { AutoRecycle = true };
_machineName = Environment.MachineName;
_netManager.DisconnectTimeout = (int)(_provider.DisconnectTimeout * 1000); _netManager.DisconnectTimeout = (int)(_provider.DisconnectTimeout * 1000);
_netManager.ReconnectDelay = (int)(_provider.ReconnectInterval * 1000); _netManager.ReconnectDelay = (int)(_provider.ReconnectInterval * 1000);
_netManager.MaxConnectAttempts = _provider.MaxConnectAttempts; _netManager.MaxConnectAttempts = _provider.MaxConnectAttempts;
_netManager.UpdateTime = (int)(_provider.UpdateInterval * 1000); _netManager.UpdateTime = (int)(_provider.UpdateInterval * 1000);
for (int i = 0; i < Engine.Config.MaxPlayers; i++) for (int i = 0; i < Engine.Config.MaxPlayers; i++)
_freeClients.Enqueue(new LNLConnection(this)); _freeClients.Enqueue(new LNLConnection(this));
} }
public override void PollEvents() public override void PollEvents() => _netManager.PollEvents();
{ public override void ForceUpdate() => _netManager.TriggerUpdate();
_netManager.PollEvents();
}
public override void ForceUpdate()
{
_netManager.TriggerUpdate();
}
public override void Run(RunMode mode, int port) public override void Run(RunMode mode, int port)
{ {
_port = port;
if (mode == RunMode.Client) if (mode == RunMode.Client)
{ {
_netManager.UnconnectedMessagesEnabled = true; _netManager.UnconnectedMessagesEnabled = true;
_netManager.Start(); _netManager.Start();
} }
else else
{ {
_netManager.BroadcastReceiveEnabled = true; _netManager.BroadcastReceiveEnabled = true;
_netManager.Start(port); _netManager.Start(port);
} }
_port = port;
} }
public override void Shutdown() public override void Shutdown()
@@ -135,9 +98,7 @@ namespace Netick.Transport
_netManager.Start(); _netManager.Start();
if (connectionData == null) if (connectionData == null)
{
_netManager.Connect(address, port, ""); _netManager.Connect(address, port, "");
}
else else
{ {
_writer. Reset(); _writer. Reset();
@@ -159,9 +120,8 @@ namespace Netick.Transport
return; return;
} }
int len = request.Data.AvailableBytes; request.Data.GetBytes(_connectionBytes, 0, request.Data.AvailableBytes);
request.Data.GetBytes(_connectionBytes, 0, len); bool accepted = NetworkPeer.OnConnectRequest(_connectionBytes, request.Data.AvailableBytes, request.RemoteEndPoint.ToNetickEndPoint());
bool accepted = NetworkPeer.OnConnectRequest(_connectionBytes, len, request.RemoteEndPoint.ToNetickEndPoint());
if (accepted) if (accepted)
request.Accept(); request.Accept();
@@ -173,9 +133,8 @@ namespace Netick.Transport
{ {
var connection = _freeClients.Dequeue(); var connection = _freeClients.Dequeue();
connection.LNLPeer = peer; connection.LNLPeer = peer;
_clients. Add(peer, connection);
_clients. Add(peer, connection); NetworkPeer. OnConnected(connection);
NetworkPeer.OnConnected(connection);
} }
void INetEventListener.OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo) void INetEventListener.OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo)
@@ -200,56 +159,40 @@ namespace Netick.Transport
NetworkPeer.OnConnectFailed(ConnectionFailedReason.Refused); NetworkPeer.OnConnectFailed(ConnectionFailedReason.Refused);
return; return;
} }
} }
if (peer == null) if (peer == null)
{
return; return;
}
if (_clients.ContainsKey(peer)) if (_clients.ContainsKey(peer))
{ {
TransportDisconnectReason reason = disconnectInfo.Reason == DisconnectReason.Timeout ? TransportDisconnectReason.Timeout : TransportDisconnectReason.Shutdown; TransportDisconnectReason reason = disconnectInfo.Reason == DisconnectReason.Timeout ? TransportDisconnectReason.Timeout : TransportDisconnectReason.Shutdown;
NetworkPeer. OnDisconnected(_clients[peer], reason); NetworkPeer. OnDisconnected(_clients[peer], reason);
_freeClients.Enqueue(_clients[peer]); _freeClients.Enqueue(_clients[peer]);
_clients. Remove(peer); _clients. Remove(peer);
} }
} }
unsafe void INetEventListener.OnNetworkReceive(NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod) unsafe void INetEventListener.OnNetworkReceive(NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod)
{ {
if (_clients.TryGetValue(peer, out var c)) if (!_clients.TryGetValue(peer, out var c))
return;
fixed (byte* ptr = reader.RawData)
{ {
var len = reader.AvailableBytes; _buffer. SetFrom(ptr + reader.Position, reader.AvailableBytes, reader.RawData.Length);
NetworkPeer.Receive(c, _buffer);
if (_bytes.Length < reader.AvailableBytes)
_bytes = new byte[reader.AvailableBytes];
reader. GetBytes(_bytes, 0, reader.AvailableBytes);
fixed(byte* ptr = _bytes)
{
_buffer. SetFrom(ptr, len, _bytes.Length);
NetworkPeer.Receive(c, _buffer);
}
} }
} }
void INetEventListener.OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType)
{
}
void INetEventListener.OnNetworkError(IPEndPoint endPoint, SocketError socketError) void INetEventListener.OnNetworkError(IPEndPoint endPoint, SocketError socketError)
{ {
Debug.Log("LiteNetLib Network Error: " + socketError); Debug.Log("LiteNetLib Network Error: " + socketError);
NetworkPeer.OnConnectFailed(ConnectionFailedReason.Refused); NetworkPeer.OnConnectFailed(ConnectionFailedReason.Refused);
} }
void INetEventListener.OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType) { }
void INetEventListener.OnNetworkLatencyUpdate(NetPeer peer, int latency) { } void INetEventListener.OnNetworkLatencyUpdate(NetPeer peer, int latency) { }
} }
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "com.karrar.netick", "name": "com.karrar.netick",
"version": "0.12.67", "version": "0.12.68",
"displayName": "Netick", "displayName": "Netick",
"description": "A networking solution for Unity", "description": "A networking solution for Unity",
"unity": "2021.3", "unity": "2021.3",