Prepare for zero-copy sending

This commit is contained in:
2025-08-16 19:51:35 +03:00
parent 46d741a287
commit dfad8b9141
10 changed files with 76 additions and 26 deletions
+1 -1
View File
@@ -27,7 +27,7 @@ class Program
var listening = new IPEndPoint(IPAddress.Any, 4567);
builder.Services.Configure<GatewayOptions>(options => options.Endpoint = listening);
builder.Services.AddSingleton<IDistributionModule, ExtractorFirstDistributionModule>();
builder.Services.Configure<SerializationBufferOffset>(options => options.Offset = 0);
builder.Services.AddSingleton<HubRequestExtractor>();
builder.Services.AddSingleton<IExecuteModule, BasicExecutionModule>();
builder.Services.AddSingleton<IRepresentationModuleProducer, CreativeRepresentationModuleProducer>();
+1
View File
@@ -46,6 +46,7 @@ class Program
builder.Services.AddOptions();
builder.Services.Configure<GatewayOptions>(options => options.Endpoint = serverEndPoint);
builder.Services.Configure<DistributionOptions>(o => o.DistributionType = EDistributionType.Channeled);
builder.Services.Configure<SerializationBufferOffset>(options => options.Offset = 0);
builder.Services.AddSingleton<IRepresentationModuleProducer, StaticRepresentationModuleProducer>();
builder.Services.AddSingleton<IRequestExtractor, RequestExtractor>();
+18 -9
View File
@@ -5,6 +5,7 @@ using System.Diagnostics;
using System.Formats.Cbor;
using System.Linq;
using System.Reflection;
using Microsoft.Extensions.Options;
using mROA.Abstract;
using mROA.Implementation;
using mROA.Implementation.Attributes;
@@ -15,6 +16,11 @@ namespace mROA.Cbor
public class CborSerializationToolkit : IContextualSerializationToolKit
{
private readonly CborWriter _writer = new(initialCapacity: 2048);
private readonly int _offset;
public CborSerializationToolkit(IOptions<SerializationBufferOffset> offsetOptions) : this(offsetOptions.Value.Offset)
{
}
private readonly IOrdinaryStructureParser[] _parsers =
{
@@ -23,6 +29,12 @@ namespace mROA.Cbor
};
private readonly Dictionary<Type, List<PropertyInfo>> _propertiesCache = new();
public CborSerializationToolkit(int offset)
{
_offset = offset;
}
public static TimeSpan SerializationTime = TimeSpan.Zero;
private bool FindParser(Type t, out IOrdinaryStructureParser parser)
@@ -56,7 +68,9 @@ namespace mROA.Cbor
{
_writer.Reset();
WriteData(objectToSerialize, _writer, context);
result = _writer.Encode();
result = new byte[_offset + _writer.BytesWritten];
var span = result.AsSpan();
_writer.Encode(span[_offset..]);
}
return result;
@@ -94,18 +108,13 @@ namespace mROA.Cbor
var reader = new CborReader(rawMemory);
return ReadData(reader, type, context);
}
catch (Exception e)
catch (Exception)
{
Console.WriteLine($"Bad deserialization. Bytes: {rawMemory.ToArray().Select(b => $"{b:X}")}");
Console.WriteLine($"Bad deserialization. Bytes: {BitConverter.ToString(rawMemory.ToArray())}");
throw;
}
}
public T Cast<T>(object nonCasted, IEndPointContext? context)
{
return (T)Cast(nonCasted, typeof(T), context);
}
public object? Cast(object? nonCasted, Type type, IEndPointContext? context)
{
if (nonCasted == null)
@@ -133,7 +142,7 @@ namespace mROA.Cbor
public IContextualSerializationToolKit Clone()
{
return new CborSerializationToolkit();
return new CborSerializationToolkit(_offset) ;
}
public void WriteData(object? obj, CborWriter writer, IEndPointContext? context)
+1
View File
@@ -23,6 +23,7 @@ namespace mROA.Codegen
ReturnType = typeof(<!L returnType>),
ParameterTypes = new Type[] { <!L parametersType> },
SuitableType = typeof(<!L suitableType>),
RequireCancellation = <!L cancellation>,
Invoking = (i, parameters, special, post) => <!L funcInvoking>,
}<!T>
<!T syncInvoker>
@@ -9,6 +9,7 @@ namespace mROA.Codegen.Templates
private const string ParametersTypeTag = "parametersType";
private const string SuitableTypeTag = "suitableType";
private const string FuncInvokingTag = "funcInvoking";
private const string CancellationTag = "cancellation";
private const string IsTrustedTag = "isTrusted";
public InvokerTemplate(TemplateDocument template) : base(template) { }
@@ -42,5 +43,10 @@ namespace mROA.Codegen.Templates
{
Define(IsTrustedTag, value);
}
public void DefineCancellation(string value)
{
Define(CancellationTag, value);
}
}
}
+5
View File
@@ -316,11 +316,14 @@ namespace mROA.Codegen
var parametersInsertList = new List<string>();
var useCancellationToken = false;
foreach (var parameter in method.Parameters)
switch (parameter.Type.Name)
{
case "CancellationToken":
parametersInsertList.Add("(CancellationToken)special[1]");
useCancellationToken = true;
break;
case "RequestContext":
parametersInsertList.Add("(RequestContext)special[0]");
@@ -359,6 +362,7 @@ namespace mROA.Codegen
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
invokerTemplate.DefineFuncInvoking(funcInvoking);
invokerTemplate.DefineIsTrusted((!isUntrusted).ToString().ToLower());
invokerTemplate.DefineCancellation(useCancellationToken.ToString().ToLower());
backend = invokerTemplate.Compile();
}
else
@@ -370,6 +374,7 @@ namespace mROA.Codegen
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
invokerTemplate.DefineFuncInvoking(funcInvoking);
invokerTemplate.DefineIsTrusted((!isUntrusted).ToString().ToLower());
backend = invokerTemplate.Compile();
}
@@ -144,21 +144,30 @@ namespace mROA.Implementation.Backend
private ICommandExecution? ExecuteAsync(AsyncMethodInvoker invoker, object instance, object?[]? parameters,
CallRequest command, ICancellationRepository cancellationRepository,
IRepresentationModule representationModule, RequestContext executionContext, IEndPointContext context)
{
CancellationToken? token = null;
if (invoker.RequireCancellation)
{
var tokenSource = new CancellationTokenSource();
cancellationRepository.RegisterCancellation(command.Id, tokenSource);
var token = tokenSource.Token;
token = tokenSource.Token;
}
invoker.Invoke(instance, parameters, new object[] { executionContext, token }, _ =>
{
if (token.IsCancellationRequested)
if (invoker.RequireCancellation)
{
_cancellationRepo.FreeCancellation(command.Id);
if (token.Value.IsCancellationRequested)
return;
}
var payload = new FinalCommandExecution
{
Id = command.Id
};
_cancellationRepo.FreeCancellation(command.Id);
if (invoker.IsTrusted)
@@ -173,21 +182,32 @@ namespace mROA.Implementation.Backend
private ICommandExecution? TypedExecuteAsync(AsyncMethodInvoker invoker, object instance, object?[]? parameters,
CallRequest command, ICancellationRepository cancellationRepository,
IRepresentationModule representationModule, RequestContext executionContext, IEndPointContext context)
{
CancellationToken? token = null;
if (invoker.RequireCancellation)
{
var tokenSource = new CancellationTokenSource();
cancellationRepository.RegisterCancellation(command.Id, tokenSource);
var token = tokenSource.Token;
token = tokenSource.Token;
}
invoker.Invoke(instance, parameters, new object[] { executionContext, token },
finalResult =>
{
if (invoker.RequireCancellation)
{
_cancellationRepo.FreeCancellation(command.Id);
if (token.Value.IsCancellationRequested)
return;
}
var payload = new FinalCommandExecution<object>
{
Id = command.Id,
Result = finalResult
};
_cancellationRepo.FreeCancellation(command.Id);
representationModule.PostCallMessageAsync(command.Id, EMessageType.FinishedCommandExecution,
payload, context);
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using mROA.Abstract;
@@ -5,16 +6,16 @@ namespace mROA.Implementation
{
public class CollectableMethodRepository : IMethodRepository
{
private readonly List<IMethodInvoker> _methods = new();
private readonly List<IMethodInvoker> _methods = new() { MethodInvoker.Dispose };
private IMethodInvoker[] _baked = Array.Empty<IMethodInvoker>();
public void AppendInvokers(IEnumerable<IMethodInvoker> methodInvokers)
{
_methods.AddRange(methodInvokers);
_baked = _methods.ToArray();
}
public IMethodInvoker GetMethod(int id)
{
return id == -1 ? MethodInvoker.Dispose : _methods[id];
return _baked[++id];
}
}
}
+1 -1
View File
@@ -37,7 +37,7 @@ namespace mROA.Implementation
public Type[] ParameterTypes { get; set; } = Type.EmptyTypes;
public Type? ReturnType { get; set; }
public Type SuitableType { get; set; } = typeof(object);
public bool RequireCancellation { get; set; } = true;
public Action<object, object?[]?, object[], Action<object?>> Invoking { get; set; } =
(_, _, _, post) => { post.Invoke(null); };
@@ -0,0 +1,7 @@
namespace mROA.Implementation
{
public class SerializationBufferOffset
{
public int Offset { get; set; } = 19;
}
}