Skip to content

Commit

Permalink
feat: Implemented NetworkReaderPool (#1464)
Browse files Browse the repository at this point in the history
* Implement NetworkReaderPool

* Reset Position

* Debug logging removed

* SetBuffer methods internal

* Edited comment
  • Loading branch information
MrGadget committed Feb 1, 2020
1 parent abb570b commit 9257112
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 25 deletions.
20 changes: 14 additions & 6 deletions Assets/Mirror/Components/Discovery/NetworkDiscoveryBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,19 +147,22 @@ async Task ReceiveRequestAsync(UdpClient udpClient)

UdpReceiveResult udpReceiveResult = await udpClient.ReceiveAsync();

NetworkReader reader = new NetworkReader(udpReceiveResult.Buffer);
NetworkReader networkReader = NetworkReaderPool.GetReader(udpReceiveResult.Buffer);

long handshake = reader.ReadInt64();
long handshake = networkReader.ReadInt64();
if (handshake != secretHandshake)
{
// message is not for us
NetworkReaderPool.Recycle(networkReader);
throw new ProtocolViolationException("Invalid handshake");
}

Request request = new Request();
request.Deserialize(reader);
request.Deserialize(networkReader);

ProcessClientRequest(request, udpReceiveResult.RemoteEndPoint);

NetworkReaderPool.Recycle(networkReader);
}

/// <summary>
Expand Down Expand Up @@ -330,15 +333,20 @@ async Task ReceiveGameBroadcastAsync(UdpClient udpClient)

UdpReceiveResult udpReceiveResult = await udpClient.ReceiveAsync();

NetworkReader reader = new NetworkReader(udpReceiveResult.Buffer);
NetworkReader networkReader = NetworkReaderPool.GetReader(udpReceiveResult.Buffer);

if (reader.ReadInt64() != secretHandshake)
if (networkReader.ReadInt64() != secretHandshake)
{
NetworkReaderPool.Recycle(networkReader);
return;
}

Response response = new Response();
response.Deserialize(reader);
response.Deserialize(networkReader);

ProcessResponse(response, udpReceiveResult.RemoteEndPoint);

NetworkReaderPool.Recycle(networkReader);
}

/// <summary>
Expand Down
18 changes: 14 additions & 4 deletions Assets/Mirror/Components/NetworkAnimator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -451,15 +451,21 @@ void CmdOnAnimationServerMessage(int stateHash, float normalizedTime, int layerI
if (LogFilter.Debug) Debug.Log("OnAnimationMessage for netId=" + netId);

// handle and broadcast
HandleAnimMsg(stateHash, normalizedTime, layerId, new NetworkReader(parameters));
NetworkReader networkReader = NetworkReaderPool.GetReader(parameters);
HandleAnimMsg(stateHash, normalizedTime, layerId, networkReader);
NetworkReaderPool.Recycle(networkReader);

RpcOnAnimationClientMessage(stateHash, normalizedTime, layerId, parameters);
}

[Command]
void CmdOnAnimationParametersServerMessage(byte[] parameters)
{
// handle and broadcast
HandleAnimParamsMsg(new NetworkReader(parameters));
NetworkReader networkReader = NetworkReaderPool.GetReader(parameters);
HandleAnimParamsMsg(networkReader);
NetworkReaderPool.Recycle(networkReader);

RpcOnAnimationParametersClientMessage(parameters);
}

Expand All @@ -486,13 +492,17 @@ void CmdOnAnimationResetTriggerServerMessage(int hash)
[ClientRpc]
void RpcOnAnimationClientMessage(int stateHash, float normalizedTime, int layerId, byte[] parameters)
{
HandleAnimMsg(stateHash, normalizedTime, layerId, new NetworkReader(parameters));
NetworkReader networkReader = NetworkReaderPool.GetReader(parameters);
HandleAnimMsg(stateHash, normalizedTime, layerId, networkReader);
NetworkReaderPool.Recycle(networkReader);
}

[ClientRpc]
void RpcOnAnimationParametersClientMessage(byte[] parameters)
{
HandleAnimParamsMsg(new NetworkReader(parameters));
NetworkReader networkReader = NetworkReaderPool.GetReader(parameters);
HandleAnimParamsMsg(networkReader);
NetworkReaderPool.Recycle(networkReader);
}

[ClientRpc]
Expand Down
5 changes: 3 additions & 2 deletions Assets/Mirror/Components/NetworkTransformBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,9 @@ public override void OnDeserialize(NetworkReader reader, bool initialState)
void CmdClientToServerSync(byte[] payload)
{
// deserialize payload
NetworkReader reader = new NetworkReader(payload);
DeserializeFromReader(reader);
NetworkReader networkReader = NetworkReaderPool.GetReader(payload);
DeserializeFromReader(networkReader);
NetworkReaderPool.Recycle(networkReader);

// server-only mode does no interpolation to save computations,
// but let's set the position directly
Expand Down
15 changes: 11 additions & 4 deletions Assets/Mirror/Runtime/ClientScene.cs
Original file line number Diff line number Diff line change
Expand Up @@ -488,8 +488,9 @@ static void ApplySpawnPayload(NetworkIdentity identity, SpawnMessage msg)
// (Count is 0 if there were no components)
if (msg.payload.Count > 0)
{
NetworkReader payloadReader = new NetworkReader(msg.payload);
NetworkReader payloadReader = NetworkReaderPool.GetReader(msg.payload);
identity.OnUpdateVars(payloadReader, true);
NetworkReaderPool.Recycle(payloadReader);
}

NetworkIdentity.spawned[msg.netId] = identity;
Expand Down Expand Up @@ -683,7 +684,9 @@ internal static void OnUpdateVarsMessage(UpdateVarsMessage msg)

if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity localObject) && localObject != null)
{
localObject.OnUpdateVars(new NetworkReader(msg.payload), false);
NetworkReader networkReader = NetworkReaderPool.GetReader(msg.payload);
localObject.OnUpdateVars(networkReader, false);
NetworkReaderPool.Recycle(networkReader);
}
else
{
Expand All @@ -697,7 +700,9 @@ internal static void OnRPCMessage(RpcMessage msg)

if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity identity))
{
identity.HandleRPC(msg.componentIndex, msg.functionHash, new NetworkReader(msg.payload));
NetworkReader networkReader = NetworkReaderPool.GetReader(msg.payload);
identity.HandleRPC(msg.componentIndex, msg.functionHash, networkReader);
NetworkReaderPool.Recycle(networkReader);
}
}

Expand All @@ -707,7 +712,9 @@ internal static void OnSyncEventMessage(SyncEventMessage msg)

if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity identity))
{
identity.HandleSyncEvent(msg.componentIndex, msg.functionHash, new NetworkReader(msg.payload));
NetworkReader networkReader = NetworkReaderPool.GetReader(msg.payload);
identity.HandleSyncEvent(msg.componentIndex, msg.functionHash, networkReader);
NetworkReaderPool.Recycle(networkReader);
}
else
{
Expand Down
12 changes: 9 additions & 3 deletions Assets/Mirror/Runtime/MessagePacker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,22 @@ public static byte[] PackMessage(int msgType, MessageBase msg)
// unpack a message we received
public static T Unpack<T>(byte[] data) where T : IMessageBase, new()
{
NetworkReader reader = new NetworkReader(data);
NetworkReader networkReader = NetworkReaderPool.GetReader(data);

int msgType = GetId<T>();

int id = reader.ReadUInt16();
int id = networkReader.ReadUInt16();
if (id != msgType)
{
NetworkReaderPool.Recycle(networkReader);
throw new FormatException("Invalid message, could not unpack " + typeof(T).FullName);
}

T message = new T();
message.Deserialize(reader);
message.Deserialize(networkReader);

NetworkReaderPool.Recycle(networkReader);

return message;
}

Expand Down
12 changes: 8 additions & 4 deletions Assets/Mirror/Runtime/NetworkConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,9 @@ internal bool InvokeHandler(int msgType, NetworkReader reader, int channelId)

MessagePacker.Pack(msg, writer);
ArraySegment<byte> segment = writer.ToArraySegment();
bool result = InvokeHandler(msgType, new NetworkReader(segment), channelId);
NetworkReader networkReader = NetworkReaderPool.GetReader(segment);
bool result = InvokeHandler(msgType, networkReader, channelId);
NetworkReaderPool.Recycle(networkReader);

// recycle writer and return
NetworkWriterPool.Recycle(writer);
Expand All @@ -345,14 +347,14 @@ internal bool InvokeHandler(int msgType, NetworkReader reader, int channelId)
internal void TransportReceive(ArraySegment<byte> buffer, int channelId)
{
// unpack message
NetworkReader reader = new NetworkReader(buffer);
if (MessagePacker.UnpackMessage(reader, out int msgType))
NetworkReader networkReader = NetworkReaderPool.GetReader(buffer);
if (MessagePacker.UnpackMessage(networkReader, out int msgType))
{
// logging
if (logNetworkMessages) Debug.Log("ConnectionRecv " + this + " msgType:" + msgType + " content:" + BitConverter.ToString(buffer.Array, buffer.Offset, buffer.Count));

// try to invoke the handler for that message
if (InvokeHandler(msgType, reader, channelId))
if (InvokeHandler(msgType, networkReader, channelId))
{
lastMessageTime = Time.time;
}
Expand All @@ -362,6 +364,8 @@ internal void TransportReceive(ArraySegment<byte> buffer, int channelId)
Debug.LogError("Closed connection: " + this + ". Invalid message header.");
Disconnect();
}

NetworkReaderPool.Recycle(networkReader);
}

internal void AddOwnedObject(NetworkIdentity obj)
Expand Down
15 changes: 14 additions & 1 deletion Assets/Mirror/Runtime/NetworkReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ public class NetworkReader
public int Position;
public int Length => buffer.Count;


public NetworkReader(byte[] bytes)
{
buffer = new ArraySegment<byte>(bytes);
Expand All @@ -39,6 +38,20 @@ public NetworkReader(ArraySegment<byte> segment)
buffer = segment;
}

// SetBuffer methods mirror constructor for ReaderPool
internal void SetBuffer(byte[] bytes)
{
buffer = new ArraySegment<byte>(bytes);
Position = 0;
}

internal void SetBuffer(ArraySegment<byte> segment)
{
buffer = segment;
Position = 0;
}


public byte ReadByte()
{
if (Position + 1 > buffer.Count)
Expand Down
41 changes: 41 additions & 0 deletions Assets/Mirror/Runtime/NetworkReaderPool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;

namespace Mirror
{
public static class NetworkReaderPool
{
static readonly Stack<NetworkReader> pool = new Stack<NetworkReader>();

public static NetworkReader GetReader(byte[] bytes)
{
if (pool.Count != 0)
{
NetworkReader reader = pool.Pop();
// reset buffer
reader.SetBuffer(bytes);
return reader;
}

return new NetworkReader(bytes);
}

public static NetworkReader GetReader(ArraySegment<byte> segment)
{
if (pool.Count != 0)
{
NetworkReader reader = pool.Pop();
// reset buffer
reader.SetBuffer(segment);
return reader;
}

return new NetworkReader(segment);
}

public static void Recycle(NetworkReader reader)
{
pool.Push(reader);
}
}
}
11 changes: 11 additions & 0 deletions Assets/Mirror/Runtime/NetworkReaderPool.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Assets/Mirror/Runtime/NetworkServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1016,7 +1016,10 @@ static void OnCommandMessage(NetworkConnection conn, CommandMessage msg)
}

if (LogFilter.Debug) Debug.Log("OnCommandMessage for netId=" + msg.netId + " conn=" + conn);
identity.HandleCommand(msg.componentIndex, msg.functionHash, new NetworkReader(msg.payload));

NetworkReader networkReader = NetworkReaderPool.GetReader(msg.payload);
identity.HandleCommand(msg.componentIndex, msg.functionHash, networkReader);
NetworkReaderPool.Recycle(networkReader);
}

internal static void SpawnObject(GameObject obj, NetworkConnection ownerConnection)
Expand Down

0 comments on commit 9257112

Please sign in to comment.