refactor: handler invocation performance
All checks were successful
Build, Package and Push Images / preprocess (push) Successful in 2s
Build, Package and Push Images / build (push) Successful in 29s
Build, Package and Push Images / sbom-scan (push) Successful in 38s
Build, Package and Push Images / sonarqube (push) Successful in 1m21s
Build, Package and Push Images / container-build (push) Successful in 1m21s
Build, Package and Push Images / container-sbom-scan (push) Successful in 33s

This commit is contained in:
Timothy Schenk 2023-11-22 14:55:46 +01:00
parent b3de52c6d8
commit a547d6ebbf
3 changed files with 37 additions and 10 deletions

View file

@ -41,7 +41,7 @@ internal static partial class PacketLoggerMessages
Message = "No PacketHandlers have been found")] Message = "No PacketHandlers have been found")]
public static partial void NoPacketHandlersFound(this ILogger logger); public static partial void NoPacketHandlersFound(this ILogger logger);
[LoggerMessage(EventId = 8, Level = LogLevel.Information, [LoggerMessage(EventId = 8, Level = LogLevel.Trace,
Message = "Packet data {PacketData}")] Message = "Packet data {PacketData}")]
public static partial void PacketData(this ILogger logger, string packetData); public static partial void PacketData(this ILogger logger, string packetData);

View file

@ -7,8 +7,24 @@ using Wonderking.Packets;
namespace Server.PacketHandlers; namespace Server.PacketHandlers;
[UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)] [UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)]
public interface IPacketHandler<in T> where T : IPacket public interface IPacketHandler<in T> : IPacketHandler where T : IPacket
{ {
[UsedImplicitly] [UsedImplicitly]
public Task HandleAsync(T packet, TcpSession session); public Task HandleAsync(T packet, TcpSession session);
async Task<bool> IPacketHandler.TryHandleAsync(IPacket packet, TcpSession session)
{
if (packet is T tPacket)
{
await HandleAsync(tPacket, session);
return true;
}
return false;
}
}
public interface IPacketHandler
{
Task<bool> TryHandleAsync(IPacket packet, TcpSession session);
} }

View file

@ -2,6 +2,7 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics;
using System.Reflection; using System.Reflection;
using DotNext.Collections.Generic; using DotNext.Collections.Generic;
using DotNext.Linq.Expressions; using DotNext.Linq.Expressions;
@ -32,13 +33,15 @@ public class PacketDistributorService : IHostedService
private ImmutableDictionary<OperationCode, private ImmutableDictionary<OperationCode,
Func<byte[], IPacket>> _deserializationMap; Func<byte[], IPacket>> _deserializationMap;
private ConcurrentDictionary<OperationCode, object> _packetHandlersInstantiation; private ConcurrentDictionary<OperationCode, IPacketHandler> _packetHandlersInstantiation;
private readonly ActivitySource _activitySource;
public PacketDistributorService(ILogger<PacketDistributorService> logger, IServiceProvider serviceProvider) public PacketDistributorService(ILogger<PacketDistributorService> logger, IServiceProvider serviceProvider)
{ {
_concurrentQueue = new ConcurrentQueue<RawPacket>(); _concurrentQueue = new ConcurrentQueue<RawPacket>();
_logger = logger; _logger = logger;
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
_activitySource = new ActivitySource(nameof(Server));
} }
public Task StartAsync(CancellationToken cancellationToken) public Task StartAsync(CancellationToken cancellationToken)
@ -49,13 +52,13 @@ public class PacketDistributorService : IHostedService
var wonderkingAssembly = Assembly.GetAssembly(typeof(IPacket)); var wonderkingAssembly = Assembly.GetAssembly(typeof(IPacket));
var packetsTypes = GetPacketsWithId(wonderkingAssembly); var packetsTypes = GetPacketsWithId(wonderkingAssembly);
var packetHandlers = GetAllPacketHandlersWithId(Assembly.GetExecutingAssembly()); var packetHandlers = GetAllPacketHandlersWithId(Assembly.GetExecutingAssembly());
_packetHandlersInstantiation = new ConcurrentDictionary<OperationCode, object>(); _packetHandlersInstantiation = new ConcurrentDictionary<OperationCode, IPacketHandler>();
packetHandlers.ForEach(x => packetHandlers.ForEach(x =>
{ {
var packetHandler = var packetHandler =
ActivatorUtilities.GetServiceOrCreateInstance(_serviceProvider, ActivatorUtilities.GetServiceOrCreateInstance(_serviceProvider,
x.Value); x.Value);
_packetHandlersInstantiation.TryAdd(x.Key, packetHandler); _packetHandlersInstantiation.TryAdd(x.Key, packetHandler as IPacketHandler);
}); });
foreach (var packetsType in packetsTypes) foreach (var packetsType in packetsTypes)
{ {
@ -152,6 +155,7 @@ public class PacketDistributorService : IHostedService
private void InvokePacketHandler(RawPacket item) private void InvokePacketHandler(RawPacket item)
{ {
IPacket packet;
_logger.PacketDequeued(item.Session.Id, item.OperationCode); _logger.PacketDequeued(item.Session.Id, item.OperationCode);
if (!_deserializationMap.TryGetValue(item.OperationCode, out var value)) if (!_deserializationMap.TryGetValue(item.OperationCode, out var value))
{ {
@ -159,12 +163,19 @@ public class PacketDistributorService : IHostedService
return; return;
} }
var packet = value(item.MessageBody); using (var packetParsingActivity = _activitySource.StartActivity("PacketParsing"))
_logger.PacketData(JsonConvert.SerializeObject(packet)); {
_packetHandlersInstantiation[item.OperationCode].GetType() packetParsingActivity?.SetTag("PacketId", item.OperationCode);
.GetMethod(nameof(IPacketHandler<IPacket>.HandleAsync)) packet = value(item.MessageBody);
?.Invoke(_packetHandlersInstantiation[item.OperationCode], new object[] { packet, item.Session }); }
using (var packetHandlerActivity = _activitySource.StartActivity("PacketHandler"))
{
packetHandlerActivity?.SetTag("PacketId", item.OperationCode);
_ = _packetHandlersInstantiation[item.OperationCode].TryHandleAsync(packet, item.Session);
}
_logger.PacketData(JsonConvert.SerializeObject(packet));
_logger.PacketFinished(item.Session.Id, item.OperationCode); _logger.PacketFinished(item.Session.Id, item.OperationCode);
} }
} }