Производительность выше крыши

This commit is contained in:
2025-02-19 20:10:19 +03:00
parent 50236c6309
commit 97f7fc2967
11 changed files with 121 additions and 56 deletions
+1
View File
@@ -71,6 +71,7 @@ var x = 0;
for (int i = 0; i < iterations; i++) for (int i = 0; i < iterations; i++)
{ {
x = loadSingleton.Next(x); x = loadSingleton.Next(x);
// Console.WriteLine(x);
} }
timer.Stop(); timer.Stop();
-1
View File
@@ -31,7 +31,6 @@ public class NextGenTest
{ {
_listener.Start(); _listener.Start();
_interactionModuleB.BaseStream = _listener.AcceptTcpClient().GetStream(); _interactionModuleB.BaseStream = _listener.AcceptTcpClient().GetStream();
foreach (var guid in guids) foreach (var guid in guids)
{ {
_interactionModuleB.PostMessage(new NetworkMessage { Id = guid, Data = "Hello user"u8.ToArray() }); _interactionModuleB.PostMessage(new NetworkMessage { Id = guid, Data = "Hello user"u8.ToArray() });
+1 -1
View File
@@ -5,7 +5,7 @@ namespace mROA.Abstract;
public interface INextGenerationInteractionModule : IInjectableModule public interface INextGenerationInteractionModule : IInjectableModule
{ {
int ConnectionId { get; } int ConnectionId { get; }
public Stream? BaseStream { get; set; } public Stream BaseStream { get; set; }
NetworkMessage[] UnhandledMessages { get; } NetworkMessage[] UnhandledMessages { get; }
NetworkMessage LastMessage { get; } NetworkMessage LastMessage { get; }
EventWaitHandle CurrentReceivingHandle { get; } EventWaitHandle CurrentReceivingHandle { get; }
+4 -2
View File
@@ -1,3 +1,4 @@
using System.Windows.Input;
using mROA.Implementation; using mROA.Implementation;
using mROA.Implementation.CommandExecution; using mROA.Implementation.CommandExecution;
@@ -20,9 +21,10 @@ public interface ISerialisationModule : IInjectableModule
public interface IRepresentationModule : IInjectableModule public interface IRepresentationModule : IInjectableModule
{ {
int Id { get; } int Id { get; }
Task<T> GetMessageAsync<T>(Guid? requestId = null, MessageType? messageType = null); Task<T> GetMessageAsync<T>(Guid? requestId = null, MessageType? messageType = null, CancellationToken token = default);
T GetMessage<T>(Guid? requestId = null, MessageType? messageType = null); T GetMessage<T>(Guid? requestId = null, MessageType? messageType = null);
Task<byte[]> GetRawMessage(Guid? requestId = null, MessageType? messageType = null); T GetMessage<T>(Predicate<NetworkMessage> filter);
Task<byte[]> GetRawMessage(Predicate<NetworkMessage> filter, CancellationToken token = default);
Task PostCallMessageAsync<T>(Guid id, MessageType messageType, T payload) where T : notnull; Task PostCallMessageAsync<T>(Guid id, MessageType messageType, T payload) where T : notnull;
Task PostCallMessageAsync(Guid id, MessageType messageType, object payload, Type payloadType); Task PostCallMessageAsync(Guid id, MessageType messageType, object payload, Type payloadType);
@@ -68,7 +68,7 @@ public class NetworkGatewayModule : IGatewayModule
interaction!.Inject(_serialization); interaction!.Inject(_serialization);
interaction.BaseStream = client.GetStream(); interaction.BaseStream = client.GetStream();
interaction.StartInfiniteReceiving();
interaction.PostMessage(new NetworkMessage interaction.PostMessage(new NetworkMessage
{ {
Id = Guid.NewGuid(), SchemaId = MessageType.IdAssigning, Id = Guid.NewGuid(), SchemaId = MessageType.IdAssigning,
@@ -32,12 +32,16 @@ public class NetworkFrontendBridge(IPEndPoint ipEndPoint) : IFrontendBridge
_tcpClient.Connect(ipEndPoint); _tcpClient.Connect(ipEndPoint);
_interactionModule.BaseStream = _tcpClient.GetStream(); _interactionModule.BaseStream = _tcpClient.GetStream();
var welcomeMessage = _interactionModule.GetNextMessageReceiving().GetAwaiter().GetResult(); _interactionModule.StartInfiniteReceiving();
var handle = _interactionModule.CurrentReceivingHandle;
handle.WaitOne();
var welcomeMessage = _interactionModule.LastMessage;
if (welcomeMessage.SchemaId != MessageType.IdAssigning) if (welcomeMessage.SchemaId != MessageType.IdAssigning)
{ {
throw new Exception($"Incorrect message type. Must be IdAssigning, current : {welcomeMessage.SchemaId.ToString()}"); throw new Exception($"Incorrect message type. Must be IdAssigning, current : {welcomeMessage.SchemaId.ToString()}");
} }
_interactionModule.HandleMessage(welcomeMessage);
TransmissionConfig.OwnershipRepository = new StaticOwnershipRepository(_serialization.Deserialize<IdAssingnment>(welcomeMessage.Data)!.Id); TransmissionConfig.OwnershipRepository = new StaticOwnershipRepository(_serialization.Deserialize<IdAssingnment>(welcomeMessage.Data)!.Id);
} }
} }
@@ -56,13 +56,13 @@ public class RequestExtractor : IRequestExtractor
try try
{ {
var lastCommandId = Guid.Empty;
while (true) while (true)
{ {
var request = var request =
_representationModule!.GetMessage<DefaultCallRequest>(messageType: MessageType.CallRequest); _representationModule!.GetMessage<DefaultCallRequest>(m => m.Id != lastCommandId && m.SchemaId == MessageType.CallRequest);
lastCommandId = request.Id;
// Console.WriteLine("Executing {0}", request.Id);
if (request.Parameter is not null) if (request.Parameter is not null)
{ {
var parameterType = _methodRepository!.GetMethod(request.CommandId).GetParameters().First() var parameterType = _methodRepository!.GetMethod(request.CommandId).GetParameters().First()
+15 -2
View File
@@ -1,19 +1,32 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
// ReSharper disable UnusedMember.Global // ReSharper disable UnusedMember.Global
namespace mROA.Implementation; namespace mROA.Implementation;
public class NetworkMessage public class NetworkMessage
{ {
public static readonly NetworkMessage Null = new() {SchemaId = MessageType.Unknown, Id = Guid.Empty, Data = []}; public static readonly NetworkMessage Null = new() { SchemaId = MessageType.Unknown, Id = Guid.Empty, Data = [] };
public Guid Id { get; init; } public Guid Id { get; init; }
[JsonConverter(typeof(JsonStringEnumConverter))] [JsonConverter(typeof(JsonStringEnumConverter))]
public MessageType SchemaId { get; init; } public MessageType SchemaId { get; init; }
public required byte[] Data { get; init; } public required byte[] Data { get; init; }
public bool IsValidMessage(Guid? requestId = null, MessageType? messageType = null)
{
return (requestId is null || Id == requestId) &&
(messageType is null || SchemaId == messageType);
}
} }
public enum MessageType public enum MessageType
{ {
Unknown, FinishedCommandExecution, ExceptionCommandExecution, AsyncCancelCommandExecution, CallRequest, IdAssigning Unknown,
FinishedCommandExecution,
ExceptionCommandExecution,
AsyncCancelCommandExecution,
CallRequest,
IdAssigning
} }
@@ -6,14 +6,14 @@ public class NextGenerationInteractionModule : INextGenerationInteractionModule
{ {
private ISerializationToolkit? _serialization; private ISerializationToolkit? _serialization;
public int ConnectionId { get; private set; } public int ConnectionId { get; private set; }
public Stream? BaseStream { get; set; } public Stream BaseStream { get; set; } = Stream.Null;
private Task<NetworkMessage>? _currentReceiving; private Task<NetworkMessage>? _currentReceiving;
private const int BufferSize = ushort.MaxValue; private const int BufferSize = ushort.MaxValue;
private readonly Memory<byte> _buffer = new byte[BufferSize]; private readonly Memory<byte> _buffer = new byte[BufferSize];
private readonly List<NetworkMessage> _messageBuffer = new (128); private readonly List<NetworkMessage> _messageBuffer = new (128);
public NetworkMessage[] UnhandledMessages => _messageBuffer.ToArray(); public NetworkMessage[] UnhandledMessages => _messageBuffer.ToArray();
public NetworkMessage LastMessage { get; private set; } = NetworkMessage.Null; public NetworkMessage LastMessage { get; private set; } = NetworkMessage.Null;
public EventWaitHandle CurrentReceivingHandle { get; private set; } = new(false, EventResetMode.ManualReset); public EventWaitHandle CurrentReceivingHandle { get; private set; } = new(true, EventResetMode.ManualReset);
public void Inject<T>(T dependency) public void Inject<T>(T dependency)
{ {
@@ -31,14 +31,25 @@ public class NextGenerationInteractionModule : INextGenerationInteractionModule
public async void StartInfiniteReceiving() public async void StartInfiniteReceiving()
{ {
try
{
CurrentReceivingHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
await Task.Yield();
while (true) while (true)
{ {
var message = ReceiveMessage(); var message = ReceiveMessage();
LastMessage = message; LastMessage = message;
_messageBuffer.Add(message);
CurrentReceivingHandle.Set(); CurrentReceivingHandle.Set();
CurrentReceivingHandle = new EventWaitHandle(false, EventResetMode.ManualReset); CurrentReceivingHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
} }
} }
catch (Exception)
{
// ignored
}
}
@@ -71,9 +82,9 @@ public class NextGenerationInteractionModule : INextGenerationInteractionModule
_messageBuffer.Remove(message); _messageBuffer.Remove(message);
} }
public NetworkMessage? FirstByFilter(Predicate<NetworkMessage> predicate) public NetworkMessage FirstByFilter(Predicate<NetworkMessage> predicate)
{ {
return _messageBuffer.FirstOrDefault(m => predicate(m)); return _messageBuffer.FirstOrDefault(m => predicate(m)) ?? NetworkMessage.Null;
} }
private NetworkMessage GetNextMessage() private NetworkMessage GetNextMessage()
@@ -84,18 +95,17 @@ public class NextGenerationInteractionModule : INextGenerationInteractionModule
if (_serialization == null) if (_serialization == null)
throw new NullReferenceException("Serialization toolkit is null"); throw new NullReferenceException("Serialization toolkit is null");
var message = ReceiveMessage(); var message = ReceiveMessage();
_messageBuffer.Add(message); _messageBuffer.Add(message);
_currentReceiving = Task.Run(GetNextMessage); _currentReceiving = Task.Run(GetNextMessage);
return message!; return message;
} }
private NetworkMessage ReceiveMessage() private NetworkMessage ReceiveMessage()
{ {
var len = BitConverter.ToUInt16([(byte)BaseStream!.ReadByte(), (byte)BaseStream.ReadByte()]); var len = BitConverter.ToUInt16([(byte)BaseStream.ReadByte(), (byte)BaseStream.ReadByte()]);
var localSpan = _buffer.Span.Slice(0, len); var localSpan = _buffer.Span.Slice(0, len);
BaseStream.ReadExactly(localSpan); BaseStream.ReadExactly(localSpan);
+13 -4
View File
@@ -16,17 +16,26 @@ public abstract class RemoteObjectBase(int id, IRepresentationModule representat
{ CommandId = methodId, ObjectId = id, Parameter = parameter, ParameterType = parameter?.GetType() }; { CommandId = methodId, ObjectId = id, Parameter = parameter, ParameterType = parameter?.GetType() };
await representationModule.PostCallMessageAsync(request.Id, MessageType.CallRequest, request); await representationModule.PostCallMessageAsync(request.Id, MessageType.CallRequest, request);
var localTokenSource = new CancellationTokenSource();
var successResponse = var successResponse =
representationModule.GetMessageAsync<FinalCommandExecution<T>>( representationModule.GetMessageAsync<FinalCommandExecution<T>>(
messageType: MessageType.FinishedCommandExecution, requestId: request.Id); messageType: MessageType.FinishedCommandExecution, requestId: request.Id, token: localTokenSource.Token);
var errorResponse = var errorResponse =
representationModule.GetMessageAsync<ExceptionCommandExecution>( representationModule.GetMessageAsync<ExceptionCommandExecution>(
messageType: MessageType.ExceptionCommandExecution, requestId: request.Id); messageType: MessageType.ExceptionCommandExecution, requestId: request.Id, token: localTokenSource.Token);
Task.WaitAny(successResponse, errorResponse); Task.WaitAny(successResponse, errorResponse);
if (successResponse.IsCompletedSuccessfully)
return successResponse.Result.Result!;
if (successResponse.IsCompletedSuccessfully)
{
await localTokenSource.CancelAsync();
return successResponse.Result.Result!;
}
await localTokenSource.CancelAsync();
throw errorResponse.Result.GetException(); throw errorResponse.Result.GetException();
} }
+43 -16
View File
@@ -22,47 +22,74 @@ public class RepresentationModule : IRepresentationModule
public int Id => (_interaction ?? throw new NullReferenceException("Interaction is not initialized")).ConnectionId; public int Id => (_interaction ?? throw new NullReferenceException("Interaction is not initialized")).ConnectionId;
public async Task<T> GetMessageAsync<T>(Guid? requestId, MessageType? messageType) public async Task<T> GetMessageAsync<T>(Guid? requestId, MessageType? messageType,
CancellationToken token = default)
{ {
if (_serialization == null) if (_serialization == null)
throw new NullReferenceException("Serialization toolkit is not initialized"); throw new NullReferenceException("Serialization toolkit is not initialized");
return _serialization.Deserialize<T>(await GetRawMessage(requestId, messageType))!; return _serialization.Deserialize<T>(await GetRawMessage(m => m.IsValidMessage(requestId, messageType), token))!;
} }
public T GetMessage<T>(Guid? requestId = null, MessageType? messageType = null) public T GetMessage<T>(Guid? requestId = null, MessageType? messageType = null)
{
return GetMessage<T>(m => m.IsValidMessage(requestId, messageType));
}
public T GetMessage<T>(Predicate<NetworkMessage> filter)
{ {
if (_serialization == null) if (_serialization == null)
throw new NullReferenceException("Serialization toolkit is not initialized"); throw new NullReferenceException("Serialization toolkit is not initialized");
return _serialization.Deserialize<T>(GetRawMessage(requestId, messageType).GetAwaiter().GetResult())!; return _serialization.Deserialize<T>(GetRawMessage(filter).GetAwaiter().GetResult())!;
} }
public async Task<byte[]> GetRawMessage(Guid? requestId = null, MessageType? messageType = null) public async Task<byte[]> GetRawMessage(Predicate<NetworkMessage> filter, CancellationToken token = default)
{ {
await Task.Yield();
if (_interaction == null) if (_interaction == null)
throw new NullReferenceException("Interaction toolkit is not initialized"); throw new NullReferenceException("Interaction toolkit is not initialized");
var fromBuffer = // Console.WriteLine(
_interaction.FirstByFilter(message => // $"{DateTime.Now.TimeOfDay} {Environment.CurrentManagedThreadId} Representation : Reading");
(requestId is null || message.Id == requestId) &&
(messageType is null || message.SchemaId == messageType));
if (fromBuffer == null) if (filter(_interaction.LastMessage))
{ {
while (true) _interaction.HandleMessage(_interaction.LastMessage);
{ return _interaction.LastMessage.Data;
var message = await _interaction.GetNextMessageReceiving(); }
if ((requestId is not null && message.Id != requestId) ||
(messageType is not null && message.SchemaId != messageType)) continue;
var message = _interaction.FirstByFilter(filter);
if (message != NetworkMessage.Null)
{
_interaction.HandleMessage(message); _interaction.HandleMessage(message);
return message.Data; return message.Data;
} }
while (!token.IsCancellationRequested)
{
// Console.WriteLine(
// $"{DateTime.Now.TimeOfDay} {Environment.CurrentManagedThreadId} Representation : Receiving message...");
var handle = _interaction.CurrentReceivingHandle;
handle.WaitOne();
message = _interaction.LastMessage;
// Console.WriteLine(
// $"{DateTime.Now.TimeOfDay} {Environment.CurrentManagedThreadId} Representation : Message received {message.SchemaId} - {message.Id}");
if (!filter(message)) continue;
message = _interaction.LastMessage;
// Console.WriteLine(
// $"{DateTime.Now.TimeOfDay} {Environment.CurrentManagedThreadId} Representation : Message received Successfully {message.SchemaId} - {message.Id}");
_interaction.HandleMessage(message);
return message.Data;
} }
_interaction.HandleMessage(fromBuffer); return [];
return fromBuffer.Data;
} }
public async Task PostCallMessageAsync<T>(Guid id, MessageType messageType, T payload) where T : notnull public async Task PostCallMessageAsync<T>(Guid id, MessageType messageType, T payload) where T : notnull