From c29db73a0e22d6817838fa4a9474d80a7daae486 Mon Sep 17 00:00:00 2001 From: Mikhail Mitrofanov Date: Thu, 7 Aug 2025 23:39:42 +0300 Subject: [PATCH] Benchmark for execution test written --- Example.Frontend/Program.cs | 9 +- mROA.Benchmark/CborExtensions.cs | 17 ++- mROA.Benchmark/Program.cs | 2 +- mROA.Benchmark/RequestReader.cs | 38 +++++ mROA.Benchmark/RequestWriter.cs | 5 +- mROA.Benchmark/TaskWaiting.cs | 133 ++++++++++++++++++ mROA.Benchmark/mROA.Benchmark.csproj | 1 + mROA.Cbor/IOrdinaryStructureParser.cs | 25 ++-- mROA.Test/BenchmarkTest.cs | 22 +++ mROA.Test/ConcurrentTest.cs | 11 -- mROA.Test/mROA.Test.csproj | 1 + .../Backend/BasicExecutionModule.cs | 1 - 12 files changed, 237 insertions(+), 28 deletions(-) create mode 100644 mROA.Benchmark/RequestReader.cs create mode 100644 mROA.Benchmark/TaskWaiting.cs create mode 100644 mROA.Test/BenchmarkTest.cs diff --git a/Example.Frontend/Program.cs b/Example.Frontend/Program.cs index 7a6ce5a..607c6ea 100644 --- a/Example.Frontend/Program.cs +++ b/Example.Frontend/Program.cs @@ -76,7 +76,14 @@ class Program using (var disposingPrinter = factory.Create("Test")) { - disposingPrinter.SetFingerPrint(new[] { 1, 2, 3 }).ContinueWith(r => { Console.WriteLine(r.Status); }); + disposingPrinter.SetFingerPrint(new[] { 1, 2, 3 }).ContinueWith(r => + { + Console.WriteLine(r.Status); + if (r.Status == TaskStatus.Faulted) + { + Console.WriteLine(r.Exception); + } + }); await disposingPrinter.IntTest(new MyData { Id = 5, Score = 7, Name = "Test" }); DemoCheck.CreatingPrinter = true; diff --git a/mROA.Benchmark/CborExtensions.cs b/mROA.Benchmark/CborExtensions.cs index 6f5150b..1cbedc5 100644 --- a/mROA.Benchmark/CborExtensions.cs +++ b/mROA.Benchmark/CborExtensions.cs @@ -19,12 +19,12 @@ public static class CborExtensions MemoryMarshal.Write(span, ref id); writer.WriteByteString(span); } - + public static void WriteToDest(this RequestId id, Span destination) { MemoryMarshal.Write(destination, ref id); } - + [MethodImpl(MethodImplOptions.AggressiveOptimization)] public static unsafe void WriteToCborOpt(this RequestId id, CborWriter writer) { @@ -32,4 +32,17 @@ public static class CborExtensions MemoryMarshal.Write(span, ref id); writer.WriteByteString(span); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static RequestId ReadFromTrueCbor(CborReader reader) + { + var enc = reader.ReadEncodedValue(true); + return MemoryMarshal.Read(enc.Span[1..]); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static RequestId ReadFromCbor(CborReader reader) + { + var enc = reader.ReadEncodedValue(); + return MemoryMarshal.Read(enc.Span[1..]); + } } \ No newline at end of file diff --git a/mROA.Benchmark/Program.cs b/mROA.Benchmark/Program.cs index 0dc8d53..5150ab8 100644 --- a/mROA.Benchmark/Program.cs +++ b/mROA.Benchmark/Program.cs @@ -5,4 +5,4 @@ using mROA.Benchmark; Console.WriteLine("Hello, World!"); -BenchmarkRunner.Run(); \ No newline at end of file +BenchmarkRunner.Run(); \ No newline at end of file diff --git a/mROA.Benchmark/RequestReader.cs b/mROA.Benchmark/RequestReader.cs new file mode 100644 index 0000000..91114ae --- /dev/null +++ b/mROA.Benchmark/RequestReader.cs @@ -0,0 +1,38 @@ +using System.Formats.Cbor; +using BenchmarkDotNet.Attributes; +using mROA.Implementation; + +namespace mROA.Benchmark; + +[MemoryDiagnoser] +[DisassemblyDiagnoser] +public class RequestReader +{ + private ReadOnlyMemory _data; + + public RequestReader() + { + _data = new ReadOnlyMemory([80, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); + } + + [Benchmark(Baseline = true)] + public ulong DefaultRead() + { + var reader = new CborReader(_data); + return new RequestId(reader.ReadByteString()).P0; + } + + [Benchmark] + public ulong MemoryRead() + { + var reader = new CborReader(_data); + return CborExtensions.ReadFromCbor(reader).P0; + } + + [Benchmark] + public ulong MemoryTrueRead() + { + var reader = new CborReader(_data); + return CborExtensions.ReadFromTrueCbor(reader).P0; + } +} \ No newline at end of file diff --git a/mROA.Benchmark/RequestWriter.cs b/mROA.Benchmark/RequestWriter.cs index 4ccd89f..b9cd279 100644 --- a/mROA.Benchmark/RequestWriter.cs +++ b/mROA.Benchmark/RequestWriter.cs @@ -5,9 +5,8 @@ using mROA.Implementation; [MemoryDiagnoser] public class RequestWriter { - private const int N = 1000; - public RequestId Id = RequestId.Generate(); - private CborWriter _writer; + public RequestId Id; + private readonly CborWriter _writer; public RequestWriter() { diff --git a/mROA.Benchmark/TaskWaiting.cs b/mROA.Benchmark/TaskWaiting.cs new file mode 100644 index 0000000..c13ede7 --- /dev/null +++ b/mROA.Benchmark/TaskWaiting.cs @@ -0,0 +1,133 @@ +using BenchmarkDotNet.Attributes; +using mROA.Abstract; +using mROA.Cbor; +using mROA.Implementation; +using mROA.Implementation.Attributes; +using mROA.Implementation.Backend; +using mROA.Implementation.CommandExecution; + +namespace mROA.Benchmark; + +public class TaskWaiting +{ + private readonly BasicExecutionModule _executionModule; + private readonly CallRequest _syncRequest; + private readonly CallRequest _asyncRequest; + private readonly InstanceRepository _instanceRepo; + private readonly EndPointContext _endPointContext; + private readonly FastRepresentationModule _representationModule; + public TaskWaiting() + { + _executionModule = new BasicExecutionModule(new CancellationRepository(), new TestMethodRepo(), new CborSerializationToolkit()); + _syncRequest = new CallRequest{CommandId = 0, Parameters = null, Id = RequestId.Generate(), ObjectId = new ComplexObjectIdentifier(-1, 0)}; + _asyncRequest = new CallRequest{CommandId = 1, Parameters = null, Id = RequestId.Generate(), ObjectId = new ComplexObjectIdentifier(-1, 0)}; + _instanceRepo = new InstanceRepository(null); + _instanceRepo.FillSingletons(typeof(TaskWaiting).Assembly); + _endPointContext = new EndPointContext(_instanceRepo, null) + { + OwnerId = 0 + }; + _representationModule = new FastRepresentationModule(); + } + + [Benchmark(Baseline = true)] + public int DefaultJob() + { + return (int)((FinalCommandExecution)_executionModule.Execute(_syncRequest, _instanceRepo, _representationModule, _endPointContext)).Result; + } + + [Benchmark] + public async Task DefaultJobAsync() + { + _representationModule.Signal = new TaskCompletionSource(); + var task = _representationModule.Signal.Task; + _ = _executionModule.Execute(_asyncRequest, _instanceRepo, _representationModule, _endPointContext); + _ = await task; + return (int)((FinalCommandExecution)_representationModule.Result).Result; + } +} + +public class TestMethodRepo : IMethodRepository +{ + public IMethodInvoker GetMethod(int id) + { + if (id == 0) + return new MethodInvoker + { + IsVoid = false, + IsTrusted = true, + ReturnType = typeof(int), + ParameterTypes = Type.EmptyTypes, + SuitableType = typeof(IJobClass), + Invoking = (i, _, _) => (i as IJobClass).A() + }; + + return new AsyncMethodInvoker + { + IsVoid = false, + IsTrusted = true, + ReturnType = typeof(int), + ParameterTypes = Type.EmptyTypes, + SuitableType = typeof(IJobClass), + Invoking = (i, _, _, post) => (i as IJobClass).B().ContinueWith(task => post(task.Result)) + }; + } +} + +[SharedObjectInterface] +public interface IJobClass +{ + int A(); + Task B(); +} + +[SharedObjectSingleton] +public class JobClass : IJobClass +{ + private readonly RequestWriter _requestWriter = new(); + public int A() + { + return _requestWriter.DefaultCbor(); + } + + public Task B() + { + return Task.FromResult(_requestWriter.DefaultCbor()); + } +} + +public class FastRepresentationModule : IRepresentationModule +{ + public TaskCompletionSource Signal = new(); + + public object Result; + public int Id { get; } + public IEndPointContext Context { get; } + public Task<(object? Deserialized, EMessageType MessageType)> GetSingle(Predicate rule, IEndPointContext? context, CancellationToken token = default, params Func[] converter) + { + throw new NotImplementedException(); + } + + public IAsyncEnumerable<(object parced, EMessageType originalType)> GetStream(Predicate rule, IEndPointContext? context, CancellationToken token = default, + params Func[] converter) + { + throw new NotImplementedException(); + } + + public Task PostCallMessageAsync(RequestId id, EMessageType eMessageType, T payload, IEndPointContext? context) where T : notnull + { + Result = payload; + Signal.SetResult(0); + return Task.CompletedTask; + } + + public void PostCallMessage(RequestId id, EMessageType eMessageType, T payload, IEndPointContext? context) where T : notnull + { + throw new NotImplementedException(); + } + + public Task PostCallMessageUntrustedAsync(RequestId id, EMessageType eMessageType, T payload, IEndPointContext? context) where T : notnull + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/mROA.Benchmark/mROA.Benchmark.csproj b/mROA.Benchmark/mROA.Benchmark.csproj index a7f69a0..2bf161f 100644 --- a/mROA.Benchmark/mROA.Benchmark.csproj +++ b/mROA.Benchmark/mROA.Benchmark.csproj @@ -9,6 +9,7 @@ + diff --git a/mROA.Cbor/IOrdinaryStructureParser.cs b/mROA.Cbor/IOrdinaryStructureParser.cs index f5197c2..5ec03b5 100644 --- a/mROA.Cbor/IOrdinaryStructureParser.cs +++ b/mROA.Cbor/IOrdinaryStructureParser.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.Formats.Cbor; +using System.Runtime.InteropServices; using mROA.Abstract; using mROA.Implementation; using mROA.Implementation.CommandExecution; @@ -14,7 +16,8 @@ namespace mROA.Cbor public class CallRequestParser : IOrdinaryStructureParser { - public void Write(CborWriter writer, object value, IEndPointContext context, CborSerializationToolkit serialization) + public void Write(CborWriter writer, object value, IEndPointContext context, + CborSerializationToolkit serialization) { var v = (CallRequest)value; writer.WriteStartArray(4); @@ -33,7 +36,8 @@ namespace mROA.Cbor { Id = new RequestId(reader.ReadByteString()), CommandId = reader.ReadInt32(), - ObjectId = (ComplexObjectIdentifier)ComplexObjectIdentifierParser.Instance.Read(reader, context, serialization), + ObjectId = (ComplexObjectIdentifier)ComplexObjectIdentifierParser.Instance.Read(reader, context, + serialization), Parameters = serialization.ReadData(reader, typeof(object[]), context) as object[] }; reader.ReadEndArray(); @@ -44,7 +48,9 @@ namespace mROA.Cbor public class ComplexObjectIdentifierParser : IOrdinaryStructureParser { public static readonly ComplexObjectIdentifierParser Instance = new(); - public void Write(CborWriter writer, object value, IEndPointContext context, CborSerializationToolkit serialization) + + public void Write(CborWriter writer, object value, IEndPointContext context, + CborSerializationToolkit serialization) { writer.WriteUInt64(((ComplexObjectIdentifier)value).Flat); } @@ -58,7 +64,8 @@ namespace mROA.Cbor public class FinalCommandExecutionParser : IOrdinaryStructureParser { - public void Write(CborWriter writer, object value, IEndPointContext context, CborSerializationToolkit serialization) + public void Write(CborWriter writer, object value, IEndPointContext context, + CborSerializationToolkit serialization) { var v = (FinalCommandExecution)value; writer.WriteStartArray(2); @@ -76,18 +83,18 @@ namespace mROA.Cbor Id = new RequestId(reader.ReadByteString()), Result = serialization.ReadData(reader, typeof(object), context), }; - reader.ReadEndArray(); - return result; + reader.ReadEndArray(); + return result; } } - + public class FinalCommandExecutionResultlessParser : IOrdinaryStructureParser { - public void Write(CborWriter writer, object value, IEndPointContext context, CborSerializationToolkit serialization) + public void Write(CborWriter writer, object value, IEndPointContext context, + CborSerializationToolkit serialization) { var v = (FinalCommandExecution)value; writer.WriteStartArray(1); - // writer.WriteByteString(v.Id.ToByteArray()); v.Id.WriteToCborInline(writer); writer.WriteEndArray(); } diff --git a/mROA.Test/BenchmarkTest.cs b/mROA.Test/BenchmarkTest.cs new file mode 100644 index 0000000..3b02c66 --- /dev/null +++ b/mROA.Test/BenchmarkTest.cs @@ -0,0 +1,22 @@ +using mROA.Benchmark; + +namespace mROA.Test; + +[TestFixture] +public class BenchmarkTest +{ + + [Test] + public void Benchmark() + { + var bench = new TaskWaiting(); + var x = bench.DefaultJob(); + var y = bench.DefaultJobAsync(); + y.Wait(); + if (x == y.Result) + { + Assert.Pass(); + } + Assert.Fail(); + } +} \ No newline at end of file diff --git a/mROA.Test/ConcurrentTest.cs b/mROA.Test/ConcurrentTest.cs index 7efeacf..080663b 100644 --- a/mROA.Test/ConcurrentTest.cs +++ b/mROA.Test/ConcurrentTest.cs @@ -18,17 +18,6 @@ public class ConcurrentTest [Test] public void ParallelAlloc() { - Parallel.For(0, 100, i => - { - var data = _cmm.AllocSlice(1); - data.Span[0] = 1; - }); - - var total = _cmm.AllocSlice(100).Span; - if (total.IndexOf((byte)0) == -1) - { - Assert.Pass(); - } Assert.Fail(); } } \ No newline at end of file diff --git a/mROA.Test/mROA.Test.csproj b/mROA.Test/mROA.Test.csproj index bff76ec..ec0a9e1 100644 --- a/mROA.Test/mROA.Test.csproj +++ b/mROA.Test/mROA.Test.csproj @@ -27,6 +27,7 @@ + diff --git a/mROA/Implementation/Backend/BasicExecutionModule.cs b/mROA/Implementation/Backend/BasicExecutionModule.cs index 309908f..c794500 100644 --- a/mROA/Implementation/Backend/BasicExecutionModule.cs +++ b/mROA/Implementation/Backend/BasicExecutionModule.cs @@ -22,7 +22,6 @@ namespace mROA.Implementation.Backend public ICommandExecution? Execute(CallRequest command, IInstanceRepository instanceRepository, IRepresentationModule representationModule, IEndPointContext endPointContext) { - // _logger.LogInformation("Executing {0}", command.Id); try { var invoker = _methodRepo.GetMethod(command.CommandId);