perf: network manager registration memory allocation reduced further by removing boxing on some methods
This commit is contained in:
parent
4824496f1a
commit
e27b825990
2
Engine
2
Engine
@ -1 +1 @@
|
||||
Subproject commit 86c9ed2ba98e05f21a952b58c49af5954207e006
|
||||
Subproject commit 7a3202a053b6fd7c9adf9bc210bf8026f3412328
|
@ -15,11 +15,14 @@ public class NetworkManager : UniverseObject, INetworkManager
|
||||
private readonly Dictionary<Type, Dictionary<Type, List<MethodInfo>>> clientPacketArrivalMethods = [];
|
||||
private readonly Dictionary<Type, Dictionary<Type, List<MethodInfo>>> serverPacketArrivalMethods = [];
|
||||
|
||||
private readonly Dictionary<Type, Dictionary<string, Event<string, object>>> clientPacketRouters = [];
|
||||
private readonly Dictionary<Type, Dictionary<string, Event<string, object>>> serverPacketRouters = [];
|
||||
private readonly Dictionary<Type, Dictionary<string, object>> clientPacketRouters = [];
|
||||
private readonly Dictionary<Type, Dictionary<string, object>> serverPacketRouters = [];
|
||||
|
||||
private readonly List<(Type packetType, Delegate callback)> packetRetrievalDelegates = [];
|
||||
|
||||
private readonly Dictionary<Type, MethodInfo> clearRoutesMethods = [];
|
||||
private readonly Dictionary<Type, MethodInfo> registerPacketListenersMethods = [];
|
||||
|
||||
private readonly Dictionary<string, INetworkEntity> _networkEntities = [];
|
||||
public IReadOnlyDictionary<string, INetworkEntity> NetworkEntities => _networkEntities;
|
||||
|
||||
@ -96,37 +99,41 @@ public class NetworkManager : UniverseObject, INetworkManager
|
||||
|
||||
|
||||
private static void BroadcastPacket<T>(
|
||||
Dictionary<Type, Dictionary<string, Event<string, object>>> packetRouters,
|
||||
Dictionary<Type, Dictionary<string, object>> packetRouters,
|
||||
string senderClientId,
|
||||
T entityDataPacket)
|
||||
{
|
||||
if (!packetRouters.TryGetValue(entityDataPacket!.GetType(), out Dictionary<string, Event<string, object>>? routers))
|
||||
if (!packetRouters.TryGetValue(entityDataPacket!.GetType(), out Dictionary<string, object>? routers))
|
||||
return;
|
||||
|
||||
foreach ((string id, Event<string, object> routerEvent) in routers)
|
||||
foreach ((string id, object routerEventReference) in routers)
|
||||
{
|
||||
Event<string, T> routerEvent = (Event<string, T>)routerEventReference;
|
||||
routerEvent.Invoke(senderClientId, entityDataPacket!);
|
||||
}
|
||||
}
|
||||
|
||||
private static void RoutePacket<T>(
|
||||
Dictionary<Type, Dictionary<string, Event<string, object>>> packetRouters,
|
||||
Dictionary<Type, Dictionary<string, object>> packetRouters,
|
||||
string entityId,
|
||||
string senderClientId,
|
||||
T entityDataPacket)
|
||||
{
|
||||
if (!packetRouters.TryGetValue(entityDataPacket!.GetType(), out Dictionary<string, Event<string, object>>? routers))
|
||||
if (!packetRouters.TryGetValue(entityDataPacket!.GetType(), out Dictionary<string, object>? routers))
|
||||
return;
|
||||
|
||||
if (!routers.TryGetValue(entityId, out Event<string, object>? routerEvent))
|
||||
if (!routers.TryGetValue(entityId, out object? routerEventReference))
|
||||
return;
|
||||
|
||||
Event<string, T> routerEvent = (Event<string, T>)routerEventReference;
|
||||
routerEvent.Invoke(senderClientId, entityDataPacket!);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Packet Routers
|
||||
private static void RegisterPacketRoutersFor(
|
||||
private void RegisterPacketRoutersFor(
|
||||
INetworkEntity behaviour,
|
||||
Dictionary<Type, Dictionary<string, Event<string, object>>> packetRouters,
|
||||
Dictionary<Type, Dictionary<string, object>> packetRouters,
|
||||
Dictionary<Type, Dictionary<Type, List<MethodInfo>>> packetArrivalMethods,
|
||||
NetworkType networkType)
|
||||
{
|
||||
@ -136,34 +143,44 @@ public class NetworkManager : UniverseObject, INetworkManager
|
||||
foreach ((Type packetType, List<MethodInfo> methods) in arrivalMethods)
|
||||
foreach (MethodInfo receiveMethod in methods)
|
||||
{
|
||||
if (!packetRouters.TryGetValue(packetType, out Dictionary<string, Event<string, object>>? routers))
|
||||
if (!packetRouters.TryGetValue(packetType, out Dictionary<string, object>? routers))
|
||||
{
|
||||
routers = [];
|
||||
packetRouters.Add(packetType, routers);
|
||||
}
|
||||
|
||||
Event<string, object> packetListenerEvent = new();
|
||||
RegisterPacketListenerEvent(behaviour, packetListenerEvent, receiveMethod, networkType);
|
||||
object packetListenerEvent = CreateEventAndRegister(packetType, behaviour, networkType);
|
||||
routers.Add(behaviour.Id, packetListenerEvent);
|
||||
}
|
||||
}
|
||||
|
||||
private static void RegisterPacketListenerEvent(
|
||||
private object CreateEventAndRegister(Type packetType, INetworkEntity behaviour, NetworkType networkType)
|
||||
{
|
||||
Type genericEventType = typeof(Event<,>).MakeGenericType(typeof(string), packetType);
|
||||
object packetListenerEvent = Activator.CreateInstance(genericEventType)!;
|
||||
|
||||
if (!registerPacketListenersMethods.TryGetValue(packetType, out MethodInfo? registerPacketListenerMethod))
|
||||
throw new($"{nameof(RegisterPacketListenerEvent)} for {packetType.Name} has not been cached.");
|
||||
|
||||
registerPacketListenerMethod.Invoke(this, [behaviour, packetListenerEvent, networkType]);
|
||||
return packetListenerEvent;
|
||||
}
|
||||
|
||||
private static void RegisterPacketListenerEvent<T>(
|
||||
INetworkEntity behaviour,
|
||||
Event<string, object> packetListenerEvent,
|
||||
MethodInfo receiveMethod,
|
||||
Event<string, T> packetListenerEvent,
|
||||
NetworkType networkType)
|
||||
{
|
||||
switch (networkType)
|
||||
{
|
||||
case NetworkType.Client: packetListenerEvent.AddListener((sender, @object) => receiveMethod.Invoke(behaviour, [@object])); break;
|
||||
case NetworkType.Server: packetListenerEvent.AddListener((sender, @object) => receiveMethod.Invoke(behaviour, [sender, @object])); break;
|
||||
case NetworkType.Client: packetListenerEvent.AddListener((sender, packet) => ((IPacketListenerClient<T>)behaviour).OnClientPacketArrived(packet)); break;
|
||||
case NetworkType.Server: packetListenerEvent.AddListener((sender, packet) => ((IPacketListenerServer<T>)behaviour).OnServerPacketArrived(sender, packet)); break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void UnregisterPacketRoutersFor(
|
||||
private void UnregisterPacketRoutersFor(
|
||||
INetworkEntity behaviour,
|
||||
Dictionary<Type, Dictionary<string, Event<string, object>>> packetRouters,
|
||||
Dictionary<Type, Dictionary<string, object>> packetRouters,
|
||||
Dictionary<Type, Dictionary<Type, List<MethodInfo>>> packetArrivalMethods)
|
||||
{
|
||||
if (!packetArrivalMethods.TryGetValue(behaviour.GetType(), out Dictionary<Type, List<MethodInfo>>? arrivalMethods))
|
||||
@ -171,16 +188,25 @@ public class NetworkManager : UniverseObject, INetworkManager
|
||||
|
||||
foreach ((Type packetType, List<MethodInfo> methods) in arrivalMethods)
|
||||
{
|
||||
if (!packetRouters.TryGetValue(packetType, out Dictionary<string, Event<string, object>>? routers))
|
||||
if (!packetRouters.TryGetValue(packetType, out Dictionary<string, object>? routers))
|
||||
continue;
|
||||
|
||||
if (!routers.TryGetValue(behaviour.Id, out Event<string, object>? routerEvent))
|
||||
if (!routers.TryGetValue(behaviour.Id, out object? routerEventReference))
|
||||
continue;
|
||||
|
||||
routers.Remove(behaviour.Id);
|
||||
routerEvent.Clear();
|
||||
if (!clearRoutesMethods.TryGetValue(packetType, out MethodInfo? clearRouterMethod))
|
||||
continue;
|
||||
|
||||
clearRouterMethod.Invoke(this, [routerEventReference]);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ClearRouter<T>(object routerEventReference)
|
||||
{
|
||||
Event<string, T> routerEvent = (Event<string, T>)routerEventReference;
|
||||
routerEvent.Clear();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Engine Callbacks
|
||||
@ -217,6 +243,7 @@ public class NetworkManager : UniverseObject, INetworkManager
|
||||
public NetworkManager()
|
||||
{
|
||||
CachePacketRetrievalDelegates();
|
||||
CacheRegistrationMethods();
|
||||
CachePacketArrivalMethods();
|
||||
|
||||
_networkEntityCollector.OnCollected.AddListener(OnCollected);
|
||||
@ -242,6 +269,22 @@ public class NetworkManager : UniverseObject, INetworkManager
|
||||
}
|
||||
}
|
||||
|
||||
private void CacheRegistrationMethods()
|
||||
{
|
||||
CacheRegistrationMethods(registerPacketListenersMethods, nameof(RegisterPacketListenerEvent));
|
||||
CacheRegistrationMethods(clearRoutesMethods, nameof(ClearRouter));
|
||||
}
|
||||
|
||||
private void CacheRegistrationMethods(Dictionary<Type, MethodInfo> registrationMethods, string methodName)
|
||||
{
|
||||
MethodInfo registerPacketMethod = typeof(NetworkManager).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||
foreach ((Type packetType, Delegate callback) in packetRetrievalDelegates)
|
||||
{
|
||||
MethodInfo genericMethod = registerPacketMethod.MakeGenericMethod(packetType);
|
||||
registrationMethods.Add(packetType, genericMethod);
|
||||
}
|
||||
}
|
||||
|
||||
private void CachePacketArrivalMethods()
|
||||
{
|
||||
CachePacketArrivalMethods(clientPacketArrivalMethods, typeof(IPacketListenerClient<>), nameof(IPacketListenerClient<INetworkEntity>.OnClientPacketArrived));
|
||||
|
Loading…
x
Reference in New Issue
Block a user