feat: Implemented NetworkReaderPool (#1464)

* Implement NetworkReaderPool

* Reset Position

* Debug logging removed

* SetBuffer methods internal

* Edited comment
This commit is contained in:
MrGadget 2020-02-01 08:05:09 -05:00 committed by GitHub
parent abb570b309
commit 9257112c65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 129 additions and 25 deletions

View File

@ -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>
@ -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>

View File

@ -451,7 +451,10 @@ 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);
}
@ -459,7 +462,10 @@ void CmdOnAnimationServerMessage(int stateHash, float normalizedTime, int layerI
void CmdOnAnimationParametersServerMessage(byte[] parameters)
{
// handle and broadcast
HandleAnimParamsMsg(new NetworkReader(parameters));
NetworkReader networkReader = NetworkReaderPool.GetReader(parameters);
HandleAnimParamsMsg(networkReader);
NetworkReaderPool.Recycle(networkReader);
RpcOnAnimationParametersClientMessage(parameters);
}
@ -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]

View File

@ -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

View File

@ -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;
@ -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
{
@ -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);
}
}
@ -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
{

View File

@ -89,16 +89,22 @@ public static byte[] Pack<T>(T message) where T : IMessageBase
// 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;
}

View File

@ -325,7 +325,9 @@ public bool InvokeHandler<T>(T msg, int channelId) where T : IMessageBase
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);
@ -345,14 +347,14 @@ public bool InvokeHandler<T>(T msg, int channelId) where T : IMessageBase
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;
}
@ -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)

View File

@ -28,7 +28,6 @@ public class NetworkReader
public int Position;
public int Length => buffer.Count;
public NetworkReader(byte[] bytes)
{
buffer = new ArraySegment<byte>(bytes);
@ -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)

View File

@ -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);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2bacff63613ad634a98f9e4d15d29dbf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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)