Skip to content

Commit

Permalink
perf: Recycle argument writer to avoid allocations (#945)
Browse files Browse the repository at this point in the history
* Recycle argument writer

* Get a pooled networkwriter for argumens

* Use pool,  not static variable

* Use explicit type

* Remove blank space

* Recycle writer in the weaver where it is allocated
  • Loading branch information
paulpach authored and miwarnec committed Jul 2, 2019
1 parent d2381ce commit 9743216
Show file tree
Hide file tree
Showing 7 changed files with 25 additions and 5 deletions.
2 changes: 2 additions & 0 deletions Assets/Mirror/Editor/Weaver/Processors/CommandProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ public static MethodDefinition ProcessCommandCall(TypeDefinition td, MethodDefin
cmdWorker.Append(cmdWorker.Create(OpCodes.Ldc_I4, NetworkBehaviourProcessor.GetChannelId(ca)));
cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.sendCommandInternal));

NetworkBehaviourProcessor.WriteRecycleWriter(cmdWorker);

cmdWorker.Append(cmdWorker.Create(OpCodes.Ret));

return cmd;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,17 @@ public static void WriteSetupLocals(ILProcessor worker)
public static void WriteCreateWriter(ILProcessor worker)
{
// create writer
worker.Append(worker.Create(OpCodes.Newobj, Weaver.NetworkWriterCtor));
worker.Append(worker.Create(OpCodes.Call, Weaver.GetPooledWriterReference));
worker.Append(worker.Create(OpCodes.Stloc_0));
}

public static void WriteRecycleWriter(ILProcessor worker)
{
// NetworkWriterPool.Recycle(writer);
worker.Append(worker.Create(OpCodes.Ldloc_0));
worker.Append(worker.Create(OpCodes.Call, Weaver.RecycleWriterReference));
}

public static bool WriteArguments(ILProcessor worker, MethodDefinition md, bool skipFirst)
{
// write each argument
Expand Down
2 changes: 2 additions & 0 deletions Assets/Mirror/Editor/Weaver/Processors/RpcProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ public static MethodDefinition ProcessRpcCall(TypeDefinition td, MethodDefinitio
rpcWorker.Append(rpcWorker.Create(OpCodes.Ldc_I4, NetworkBehaviourProcessor.GetChannelId(ca)));
rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, Weaver.sendRpcInternal));

NetworkBehaviourProcessor.WriteRecycleWriter(rpcWorker);

rpcWorker.Append(rpcWorker.Create(OpCodes.Ret));

return rpc;
Expand Down
2 changes: 2 additions & 0 deletions Assets/Mirror/Editor/Weaver/Processors/SyncEventProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ public static MethodDefinition ProcessEventCall(TypeDefinition td, EventDefiniti
evtWorker.Append(evtWorker.Create(OpCodes.Ldc_I4, NetworkBehaviourProcessor.GetChannelId(ca)));
evtWorker.Append(evtWorker.Create(OpCodes.Call, Weaver.sendEventInternal));

NetworkBehaviourProcessor.WriteRecycleWriter(evtWorker);

evtWorker.Append(evtWorker.Create(OpCodes.Ret));

return evt;
Expand Down
2 changes: 2 additions & 0 deletions Assets/Mirror/Editor/Weaver/Processors/TargetRpcProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ public static MethodDefinition ProcessTargetRpcCall(TypeDefinition td, MethodDef
rpcWorker.Append(rpcWorker.Create(OpCodes.Ldc_I4, NetworkBehaviourProcessor.GetChannelId(ca)));
rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, Weaver.sendTargetRpcInternal));

NetworkBehaviourProcessor.WriteRecycleWriter(rpcWorker);

rpcWorker.Append(rpcWorker.Create(OpCodes.Ret));

return rpc;
Expand Down
5 changes: 5 additions & 0 deletions Assets/Mirror/Editor/Weaver/Weaver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ class Weaver
public static TypeReference SyncDictionaryType;

public static MethodReference NetworkBehaviourDirtyBitsReference;
public static MethodReference GetPooledWriterReference;
public static MethodReference RecycleWriterReference;
public static TypeReference NetworkClientType;
public static TypeReference NetworkServerType;

Expand Down Expand Up @@ -333,6 +335,9 @@ static void SetupTargetTypes()
SyncDictionaryType = NetAssembly.MainModule.GetType("Mirror.SyncDictionary`2");

NetworkBehaviourDirtyBitsReference = Resolvers.ResolveProperty(NetworkBehaviourType, CurrentAssembly, "syncVarDirtyBits");
TypeDefinition NetworkWriterPoolType = NetAssembly.MainModule.GetType("Mirror.NetworkWriterPool");
GetPooledWriterReference = Resolvers.ResolveMethod(NetworkWriterPoolType, CurrentAssembly, "GetWriter");
RecycleWriterReference = Resolvers.ResolveMethod(NetworkWriterPoolType, CurrentAssembly, "Recycle");

ComponentType = UnityAssembly.MainModule.GetType("UnityEngine.Component");
ClientSceneType = NetAssembly.MainModule.GetType("Mirror.ClientScene");
Expand Down
8 changes: 4 additions & 4 deletions Assets/Mirror/Runtime/NetworkBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ protected void SendCommandInternal(Type invokeClass, string cmdName, NetworkWrit
netId = netId,
componentIndex = ComponentIndex,
functionHash = GetMethodHash(invokeClass, cmdName), // type+func so Inventory.RpcUse != Equipment.RpcUse
payload = new ArraySegment<byte>(writer.ToArray()) // segment to avoid reader allocations
payload = writer.ToArraySegment() // segment to avoid reader allocations
};

ClientScene.readyConnection.Send(message, channelId);
Expand Down Expand Up @@ -157,7 +157,7 @@ protected void SendRPCInternal(Type invokeClass, string rpcName, NetworkWriter w
netId = netId,
componentIndex = ComponentIndex,
functionHash = GetMethodHash(invokeClass, rpcName), // type+func so Inventory.RpcUse != Equipment.RpcUse
payload = new ArraySegment<byte>(writer.ToArray()) // segment to avoid reader allocations
payload = writer.ToArraySegment() // segment to avoid reader allocations
};

NetworkServer.SendToReady(netIdentity, message, channelId);
Expand Down Expand Up @@ -196,7 +196,7 @@ protected void SendTargetRPCInternal(NetworkConnection conn, Type invokeClass, s
netId = netId,
componentIndex = ComponentIndex,
functionHash = GetMethodHash(invokeClass, rpcName), // type+func so Inventory.RpcUse != Equipment.RpcUse
payload = new ArraySegment<byte>(writer.ToArray()) // segment to avoid reader allocations
payload = writer.ToArraySegment() // segment to avoid reader allocations
};

conn.Send(message, channelId);
Expand Down Expand Up @@ -225,7 +225,7 @@ protected void SendEventInternal(Type invokeClass, string eventName, NetworkWrit
netId = netId,
componentIndex = ComponentIndex,
functionHash = GetMethodHash(invokeClass, eventName), // type+func so Inventory.RpcUse != Equipment.RpcUse
payload = new ArraySegment<byte>(writer.ToArray()) // segment to avoid reader allocations
payload = writer.ToArraySegment() // segment to avoid reader allocations
};

NetworkServer.SendToReady(netIdentity,message, channelId);
Expand Down

0 comments on commit 9743216

Please sign in to comment.