perf: packet listener methods are now cached for performance

This commit is contained in:
Syntriax 2025-05-26 22:09:40 +03:00
parent 29829bbaa6
commit bddf00ce7a
2 changed files with 27 additions and 31 deletions

2
Engine

@ -1 +1 @@
Subproject commit 2df41e18818e314ebfa21e578500d5e3161cf850 Subproject commit 8f8558a262a20d584afd38369b02c4c50d86b20f

View File

@ -28,8 +28,8 @@ public class NetworkManager : UniverseObject, INetworkManager
} }
} }
private readonly Dictionary<Type, Dictionary<string, object>> clientPacketListeners = []; private readonly Dictionary<Type, Dictionary<string, PacketListenerData>> clientPacketListeners = [];
private readonly Dictionary<Type, Dictionary<string, object>> serverPacketListeners = []; private readonly Dictionary<Type, Dictionary<string, PacketListenerData>> serverPacketListeners = [];
private readonly Dictionary<string, INetworkEntity> _networkEntities = []; private readonly Dictionary<string, INetworkEntity> _networkEntities = [];
public IReadOnlyDictionary<string, INetworkEntity> NetworkEntities => _networkEntities; public IReadOnlyDictionary<string, INetworkEntity> NetworkEntities => _networkEntities;
@ -98,39 +98,27 @@ public class NetworkManager : UniverseObject, INetworkManager
if (entityDataPacket is IEntityNetworkPacket entityPacket) if (entityDataPacket is IEntityNetworkPacket entityPacket)
{ {
if (networkCommunicator is INetworkCommunicatorClient) if (networkCommunicator is INetworkCommunicatorClient)
if (clientPacketListeners.TryGetValue(packetType, out Dictionary<string, object>? clientListeners)) if (clientPacketListeners.TryGetValue(packetType, out Dictionary<string, PacketListenerData>? clientListeners))
if (clientListeners.TryGetValue(entityPacket.EntityId, out object? clientListener)) if (clientListeners.TryGetValue(entityPacket.EntityId, out PacketListenerData clientListenerData))
{ clientListenerData.ListenerMethod.Invoke(clientListenerData.Object, [entityDataPacket]);
MethodInfo clientListenerReceiveMethod = typeof(IPacketListenerClient<>).MakeGenericType(packetType).GetMethods().First(m => m.Name == nameof(IPacketListenerClient<T>.OnClientPacketArrived));
clientListenerReceiveMethod.Invoke(clientListener, [entityDataPacket]);
}
if (networkCommunicator is INetworkCommunicatorServer) if (networkCommunicator is INetworkCommunicatorServer)
if (serverPacketListeners.TryGetValue(packetType, out Dictionary<string, object>? serverListeners)) if (serverPacketListeners.TryGetValue(packetType, out Dictionary<string, PacketListenerData>? serverListeners))
if (serverListeners.TryGetValue(entityPacket.EntityId, out object? serverListener)) if (serverListeners.TryGetValue(entityPacket.EntityId, out PacketListenerData serverListenerData))
{ serverListenerData.ListenerMethod.Invoke(serverListenerData.Object, [entityDataPacket, fromClientId]);
MethodInfo serverListenerReceiveMethod = typeof(IPacketListenerServer<>).MakeGenericType(packetType).GetMethods().First(m => m.Name == nameof(IPacketListenerServer<T>.OnServerPacketArrived));
serverListenerReceiveMethod.Invoke(serverListener, [entityDataPacket, fromClientId]);
}
return; return;
} }
if (networkCommunicator is INetworkCommunicatorClient) if (networkCommunicator is INetworkCommunicatorClient)
if (clientPacketListeners.TryGetValue(packetType, out Dictionary<string, object>? clientListeners)) if (clientPacketListeners.TryGetValue(packetType, out Dictionary<string, PacketListenerData>? clientListeners))
{ foreach ((string id, PacketListenerData clientListenerData) in clientListeners)
MethodInfo clientListenerReceiveMethod = typeof(IPacketListenerClient<>).MakeGenericType(packetType).GetMethods().First(m => m.Name == nameof(IPacketListenerClient<T>.OnClientPacketArrived)); clientListenerData.ListenerMethod.Invoke(clientListenerData.Object, [entityDataPacket]);
foreach ((string id, object clientListener) in clientListeners)
clientListenerReceiveMethod.Invoke(clientListener, [entityDataPacket]);
}
if (networkCommunicator is INetworkCommunicatorServer) if (networkCommunicator is INetworkCommunicatorServer)
if (serverPacketListeners.TryGetValue(packetType, out Dictionary<string, object>? serverListeners)) if (serverPacketListeners.TryGetValue(packetType, out Dictionary<string, PacketListenerData>? serverListeners))
{ foreach ((string id, PacketListenerData serverListenerData) in serverListeners)
MethodInfo serverListenerReceiveMethod = typeof(IPacketListenerServer<>).MakeGenericType(packetType).GetMethods().First(m => m.Name == nameof(IPacketListenerServer<T>.OnServerPacketArrived)); serverListenerData.ListenerMethod.Invoke(serverListenerData.Object, [entityDataPacket, fromClientId]);
foreach ((string id, object serverListener) in serverListeners)
serverListenerReceiveMethod.Invoke(serverListener, [entityDataPacket, fromClientId]);
}
} }
private void OnCollected(IBehaviourCollector<INetworkEntity> sender, INetworkEntity behaviourCollected) private void OnCollected(IBehaviourCollector<INetworkEntity> sender, INetworkEntity behaviourCollected)
@ -141,27 +129,29 @@ public class NetworkManager : UniverseObject, INetworkManager
foreach (Type clientListenerType in behaviourCollected.GetType().GetInterfaces().Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IPacketListenerClient<>))) foreach (Type clientListenerType in behaviourCollected.GetType().GetInterfaces().Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IPacketListenerClient<>)))
{ {
Type clientListenerParameterType = clientListenerType.GetGenericArguments().First(); Type clientListenerParameterType = clientListenerType.GetGenericArguments().First();
MethodInfo clientListenerReceiveMethod = clientListenerType.GetMethods().First(m => m.Name == nameof(IPacketListenerClient<INetworkEntity>.OnClientPacketArrived));
if (!clientPacketListeners.TryGetValue(clientListenerParameterType, out Dictionary<string, object>? clientListeners)) if (!clientPacketListeners.TryGetValue(clientListenerParameterType, out Dictionary<string, PacketListenerData>? clientListeners))
{ {
clientListeners = []; clientListeners = [];
clientPacketListeners.Add(clientListenerParameterType, clientListeners); clientPacketListeners.Add(clientListenerParameterType, clientListeners);
} }
clientListeners.Add(behaviourCollected.Id, behaviourCollected); clientListeners.Add(behaviourCollected.Id, new(behaviourCollected, clientListenerReceiveMethod));
} }
foreach (Type serverListenerType in behaviourCollected.GetType().GetInterfaces().Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IPacketListenerServer<>))) foreach (Type serverListenerType in behaviourCollected.GetType().GetInterfaces().Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IPacketListenerServer<>)))
{ {
Type serverListenerParameterType = serverListenerType.GetGenericArguments().First(); Type serverListenerParameterType = serverListenerType.GetGenericArguments().First();
MethodInfo serverListenerReceiveMethod = serverListenerType.GetMethods().First(m => m.Name == nameof(IPacketListenerServer<INetworkEntity>.OnServerPacketArrived));
if (!serverPacketListeners.TryGetValue(serverListenerParameterType, out Dictionary<string, object>? serverListeners)) if (!serverPacketListeners.TryGetValue(serverListenerParameterType, out Dictionary<string, PacketListenerData>? serverListeners))
{ {
serverListeners = []; serverListeners = [];
serverPacketListeners.Add(serverListenerParameterType, serverListeners); serverPacketListeners.Add(serverListenerParameterType, serverListeners);
} }
serverListeners.Add(behaviourCollected.Id, behaviourCollected); serverListeners.Add(behaviourCollected.Id, new(behaviourCollected, serverListenerReceiveMethod));
} }
} }
@ -176,4 +166,10 @@ public class NetworkManager : UniverseObject, INetworkManager
_networkEntityCollector.Assign(universe); _networkEntityCollector.Assign(universe);
NetworkCommunicator = this.GetRequiredUniverseObjectInParent<INetworkCommunicator>(); NetworkCommunicator = this.GetRequiredUniverseObjectInParent<INetworkCommunicator>();
} }
private record struct PacketListenerData(object Object, MethodInfo ListenerMethod)
{
public static implicit operator (object @object, MethodInfo listenerMethod)(PacketListenerData value) => (value.Object, value.ListenerMethod);
public static implicit operator PacketListenerData((object @object, MethodInfo listenerMethod) value) => new(value.@object, value.listenerMethod);
}
} }