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>>> clientPacketArrivalMethods = [];
|
||||||
private readonly Dictionary<Type, Dictionary<Type, List<MethodInfo>>> serverPacketArrivalMethods = [];
|
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, object>> clientPacketRouters = [];
|
||||||
private readonly Dictionary<Type, Dictionary<string, Event<string, object>>> serverPacketRouters = [];
|
private readonly Dictionary<Type, Dictionary<string, object>> serverPacketRouters = [];
|
||||||
|
|
||||||
private readonly List<(Type packetType, Delegate callback)> packetRetrievalDelegates = [];
|
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 = [];
|
private readonly Dictionary<string, INetworkEntity> _networkEntities = [];
|
||||||
public IReadOnlyDictionary<string, INetworkEntity> NetworkEntities => _networkEntities;
|
public IReadOnlyDictionary<string, INetworkEntity> NetworkEntities => _networkEntities;
|
||||||
|
|
||||||
@ -96,37 +99,41 @@ public class NetworkManager : UniverseObject, INetworkManager
|
|||||||
|
|
||||||
|
|
||||||
private static void BroadcastPacket<T>(
|
private static void BroadcastPacket<T>(
|
||||||
Dictionary<Type, Dictionary<string, Event<string, object>>> packetRouters,
|
Dictionary<Type, Dictionary<string, object>> packetRouters,
|
||||||
string senderClientId,
|
string senderClientId,
|
||||||
T entityDataPacket)
|
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;
|
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!);
|
routerEvent.Invoke(senderClientId, entityDataPacket!);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void RoutePacket<T>(
|
private static void RoutePacket<T>(
|
||||||
Dictionary<Type, Dictionary<string, Event<string, object>>> packetRouters,
|
Dictionary<Type, Dictionary<string, object>> packetRouters,
|
||||||
string entityId,
|
string entityId,
|
||||||
string senderClientId,
|
string senderClientId,
|
||||||
T entityDataPacket)
|
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;
|
return;
|
||||||
|
|
||||||
if (!routers.TryGetValue(entityId, out Event<string, object>? routerEvent))
|
if (!routers.TryGetValue(entityId, out object? routerEventReference))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Event<string, T> routerEvent = (Event<string, T>)routerEventReference;
|
||||||
routerEvent.Invoke(senderClientId, entityDataPacket!);
|
routerEvent.Invoke(senderClientId, entityDataPacket!);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Packet Routers
|
#region Packet Routers
|
||||||
private static void RegisterPacketRoutersFor(
|
private void RegisterPacketRoutersFor(
|
||||||
INetworkEntity behaviour,
|
INetworkEntity behaviour,
|
||||||
Dictionary<Type, Dictionary<string, Event<string, object>>> packetRouters,
|
Dictionary<Type, Dictionary<string, object>> packetRouters,
|
||||||
Dictionary<Type, Dictionary<Type, List<MethodInfo>>> packetArrivalMethods,
|
Dictionary<Type, Dictionary<Type, List<MethodInfo>>> packetArrivalMethods,
|
||||||
NetworkType networkType)
|
NetworkType networkType)
|
||||||
{
|
{
|
||||||
@ -136,34 +143,44 @@ public class NetworkManager : UniverseObject, INetworkManager
|
|||||||
foreach ((Type packetType, List<MethodInfo> methods) in arrivalMethods)
|
foreach ((Type packetType, List<MethodInfo> methods) in arrivalMethods)
|
||||||
foreach (MethodInfo receiveMethod in methods)
|
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 = [];
|
routers = [];
|
||||||
packetRouters.Add(packetType, routers);
|
packetRouters.Add(packetType, routers);
|
||||||
}
|
}
|
||||||
|
|
||||||
Event<string, object> packetListenerEvent = new();
|
object packetListenerEvent = CreateEventAndRegister(packetType, behaviour, networkType);
|
||||||
RegisterPacketListenerEvent(behaviour, packetListenerEvent, receiveMethod, networkType);
|
|
||||||
routers.Add(behaviour.Id, packetListenerEvent);
|
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,
|
INetworkEntity behaviour,
|
||||||
Event<string, object> packetListenerEvent,
|
Event<string, T> packetListenerEvent,
|
||||||
MethodInfo receiveMethod,
|
|
||||||
NetworkType networkType)
|
NetworkType networkType)
|
||||||
{
|
{
|
||||||
switch (networkType)
|
switch (networkType)
|
||||||
{
|
{
|
||||||
case NetworkType.Client: packetListenerEvent.AddListener((sender, @object) => receiveMethod.Invoke(behaviour, [@object])); break;
|
case NetworkType.Client: packetListenerEvent.AddListener((sender, packet) => ((IPacketListenerClient<T>)behaviour).OnClientPacketArrived(packet)); break;
|
||||||
case NetworkType.Server: packetListenerEvent.AddListener((sender, @object) => receiveMethod.Invoke(behaviour, [sender, @object])); break;
|
case NetworkType.Server: packetListenerEvent.AddListener((sender, packet) => ((IPacketListenerServer<T>)behaviour).OnServerPacketArrived(sender, packet)); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UnregisterPacketRoutersFor(
|
private void UnregisterPacketRoutersFor(
|
||||||
INetworkEntity behaviour,
|
INetworkEntity behaviour,
|
||||||
Dictionary<Type, Dictionary<string, Event<string, object>>> packetRouters,
|
Dictionary<Type, Dictionary<string, object>> packetRouters,
|
||||||
Dictionary<Type, Dictionary<Type, List<MethodInfo>>> packetArrivalMethods)
|
Dictionary<Type, Dictionary<Type, List<MethodInfo>>> packetArrivalMethods)
|
||||||
{
|
{
|
||||||
if (!packetArrivalMethods.TryGetValue(behaviour.GetType(), out Dictionary<Type, List<MethodInfo>>? arrivalMethods))
|
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)
|
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;
|
continue;
|
||||||
|
|
||||||
if (!routers.TryGetValue(behaviour.Id, out Event<string, object>? routerEvent))
|
if (!routers.TryGetValue(behaviour.Id, out object? routerEventReference))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
routers.Remove(behaviour.Id);
|
if (!clearRoutesMethods.TryGetValue(packetType, out MethodInfo? clearRouterMethod))
|
||||||
routerEvent.Clear();
|
continue;
|
||||||
|
|
||||||
|
clearRouterMethod.Invoke(this, [routerEventReference]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void ClearRouter<T>(object routerEventReference)
|
||||||
|
{
|
||||||
|
Event<string, T> routerEvent = (Event<string, T>)routerEventReference;
|
||||||
|
routerEvent.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Engine Callbacks
|
#region Engine Callbacks
|
||||||
@ -217,6 +243,7 @@ public class NetworkManager : UniverseObject, INetworkManager
|
|||||||
public NetworkManager()
|
public NetworkManager()
|
||||||
{
|
{
|
||||||
CachePacketRetrievalDelegates();
|
CachePacketRetrievalDelegates();
|
||||||
|
CacheRegistrationMethods();
|
||||||
CachePacketArrivalMethods();
|
CachePacketArrivalMethods();
|
||||||
|
|
||||||
_networkEntityCollector.OnCollected.AddListener(OnCollected);
|
_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()
|
private void CachePacketArrivalMethods()
|
||||||
{
|
{
|
||||||
CachePacketArrivalMethods(clientPacketArrivalMethods, typeof(IPacketListenerClient<>), nameof(IPacketListenerClient<INetworkEntity>.OnClientPacketArrived));
|
CachePacketArrivalMethods(clientPacketArrivalMethods, typeof(IPacketListenerClient<>), nameof(IPacketListenerClient<INetworkEntity>.OnClientPacketArrived));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user