From 5e71ce69c5d87a521b4e006fe9731d3a7a612342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6llner?= Date: Sun, 9 Feb 2020 13:49:21 +0100 Subject: [PATCH] performance optimizations --- Benchmarking/Benchmark/Benchmark.csproj | 2 +- Benchmarking/CapnpProfile.sln | 25 ++++++++++++++++ Benchmarking/CapnpProfile/CapnpProfile.csproj | 13 ++++++++ Benchmarking/CapnpProfile/Program.cs | 30 +++++++++++++++++++ Benchmarking/CapnpProfile/Protos/Echo.capnp | 5 ++++ .../CapnpProfile/Services/CapnpEchoService.cs | 20 +++++++++++++ .../EchoServiceCapnp/EchoServiceCapnp.csproj | 4 +-- Benchmarking/nuget.config | 10 +++++++ Capnp.Net.Runtime/DeserializerState.cs | 18 +++++------ Capnp.Net.Runtime/ListDeserializer.cs | 2 +- Capnp.Net.Runtime/ListOfBitsDeserializer.cs | 4 +-- Capnp.Net.Runtime/ListOfCapsDeserializer.cs | 2 +- Capnp.Net.Runtime/ListOfEmptyDeserializer.cs | 4 +-- .../ListOfPointersDeserializer.cs | 4 +-- .../ListOfPrimitivesDeserializer.cs | 13 ++++---- .../ListOfStructsDeserializer.cs | 4 +-- 16 files changed, 130 insertions(+), 30 deletions(-) create mode 100644 Benchmarking/CapnpProfile.sln create mode 100644 Benchmarking/CapnpProfile/CapnpProfile.csproj create mode 100644 Benchmarking/CapnpProfile/Program.cs create mode 100644 Benchmarking/CapnpProfile/Protos/Echo.capnp create mode 100644 Benchmarking/CapnpProfile/Services/CapnpEchoService.cs create mode 100644 Benchmarking/nuget.config diff --git a/Benchmarking/Benchmark/Benchmark.csproj b/Benchmarking/Benchmark/Benchmark.csproj index 805886e..aae7298 100644 --- a/Benchmarking/Benchmark/Benchmark.csproj +++ b/Benchmarking/Benchmark/Benchmark.csproj @@ -7,7 +7,7 @@ - + diff --git a/Benchmarking/CapnpProfile.sln b/Benchmarking/CapnpProfile.sln new file mode 100644 index 0000000..3167001 --- /dev/null +++ b/Benchmarking/CapnpProfile.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29728.190 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CapnpProfile", "CapnpProfile\CapnpProfile.csproj", "{D2D3AE23-C19E-47C7-B758-E2259DC01B5A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D2D3AE23-C19E-47C7-B758-E2259DC01B5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D2D3AE23-C19E-47C7-B758-E2259DC01B5A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D2D3AE23-C19E-47C7-B758-E2259DC01B5A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D2D3AE23-C19E-47C7-B758-E2259DC01B5A}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F5DDDA09-394B-4A71-B6BE-C7103BCEF3A2} + EndGlobalSection +EndGlobal diff --git a/Benchmarking/CapnpProfile/CapnpProfile.csproj b/Benchmarking/CapnpProfile/CapnpProfile.csproj new file mode 100644 index 0000000..0edbb3f --- /dev/null +++ b/Benchmarking/CapnpProfile/CapnpProfile.csproj @@ -0,0 +1,13 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + diff --git a/Benchmarking/CapnpProfile/Program.cs b/Benchmarking/CapnpProfile/Program.cs new file mode 100644 index 0000000..98c09c4 --- /dev/null +++ b/Benchmarking/CapnpProfile/Program.cs @@ -0,0 +1,30 @@ +using Capnp.Rpc; +using CapnpGen; +using CapnpProfile.Services; +using System; +using System.Net; +using System.Threading.Tasks; + +namespace CapnpProfile +{ + class Program + { + static async Task Main(string[] args) + { + using var server = new TcpRpcServer(IPAddress.Any, 5002); + server.Main = new CapnpEchoService(); + using var client = new TcpRpcClient("localhost", 5002); + await client.WhenConnected; + using var echoer = client.GetMain(); + var payload = new byte[200000]; + new Random().NextBytes(payload); + + while (true) + { + var result = await echoer.Echo(payload); + if (result.Count != payload.Length) + throw new InvalidOperationException("Echo server malfunction"); + } + } + } +} diff --git a/Benchmarking/CapnpProfile/Protos/Echo.capnp b/Benchmarking/CapnpProfile/Protos/Echo.capnp new file mode 100644 index 0000000..2af55d5 --- /dev/null +++ b/Benchmarking/CapnpProfile/Protos/Echo.capnp @@ -0,0 +1,5 @@ +@0x8c309c720de8cf7c; + +interface Echoer { + echo @0 (input : Data) -> (output : Data); +} diff --git a/Benchmarking/CapnpProfile/Services/CapnpEchoService.cs b/Benchmarking/CapnpProfile/Services/CapnpEchoService.cs new file mode 100644 index 0000000..426c75c --- /dev/null +++ b/Benchmarking/CapnpProfile/Services/CapnpEchoService.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace CapnpProfile.Services +{ + public class CapnpEchoService : CapnpGen.IEchoer + { + public void Dispose() + { + } + + public Task> Echo(IReadOnlyList input, CancellationToken cancellationToken_ = default) + { + return Task.FromResult(input); + } + } +} diff --git a/Benchmarking/EchoServiceCapnp/EchoServiceCapnp.csproj b/Benchmarking/EchoServiceCapnp/EchoServiceCapnp.csproj index f50d2fa..0944fa3 100644 --- a/Benchmarking/EchoServiceCapnp/EchoServiceCapnp.csproj +++ b/Benchmarking/EchoServiceCapnp/EchoServiceCapnp.csproj @@ -1,4 +1,4 @@ - + Exe @@ -6,7 +6,7 @@ - + diff --git a/Benchmarking/nuget.config b/Benchmarking/nuget.config new file mode 100644 index 0000000..7fcd85c --- /dev/null +++ b/Benchmarking/nuget.config @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Capnp.Net.Runtime/DeserializerState.cs b/Capnp.Net.Runtime/DeserializerState.cs index 8dd7ce8..e6afb8b 100644 --- a/Capnp.Net.Runtime/DeserializerState.cs +++ b/Capnp.Net.Runtime/DeserializerState.cs @@ -516,28 +516,28 @@ namespace Capnp switch (Kind) { case ObjectKind.ListOfBits: - return new ListOfBitsDeserializer(ref this, false); + return new ListOfBitsDeserializer(this, false); case ObjectKind.ListOfBytes: - return new ListOfPrimitivesDeserializer(ref this, ListKind.ListOfBytes); + return new ListOfPrimitivesDeserializer(this, ListKind.ListOfBytes); case ObjectKind.ListOfEmpty: - return new ListOfEmptyDeserializer(ref this); + return new ListOfEmptyDeserializer(this); case ObjectKind.ListOfInts: - return new ListOfPrimitivesDeserializer(ref this, ListKind.ListOfInts); + return new ListOfPrimitivesDeserializer(this, ListKind.ListOfInts); case ObjectKind.ListOfLongs: - return new ListOfPrimitivesDeserializer(ref this, ListKind.ListOfLongs); + return new ListOfPrimitivesDeserializer(this, ListKind.ListOfLongs); case ObjectKind.ListOfPointers: - return new ListOfPointersDeserializer(ref this); + return new ListOfPointersDeserializer(this); case ObjectKind.ListOfShorts: - return new ListOfPrimitivesDeserializer(ref this, ListKind.ListOfShorts); + return new ListOfPrimitivesDeserializer(this, ListKind.ListOfShorts); case ObjectKind.ListOfStructs: - return new ListOfStructsDeserializer(ref this); + return new ListOfStructsDeserializer(this); case ObjectKind.Nil: return new EmptyListDeserializer(); @@ -557,7 +557,7 @@ namespace Capnp switch (Kind) { case ObjectKind.ListOfPointers: - return new ListOfCapsDeserializer(ref this); + return new ListOfCapsDeserializer(this); default: throw new DeserializationException("Cannot deserialize this object as capability list"); diff --git a/Capnp.Net.Runtime/ListDeserializer.cs b/Capnp.Net.Runtime/ListDeserializer.cs index 8db896b..e28b90c 100644 --- a/Capnp.Net.Runtime/ListDeserializer.cs +++ b/Capnp.Net.Runtime/ListDeserializer.cs @@ -34,7 +34,7 @@ namespace Capnp /// protected readonly DeserializerState State; - internal ListDeserializer(ref DeserializerState state) + internal ListDeserializer(in DeserializerState state) { State = state; } diff --git a/Capnp.Net.Runtime/ListOfBitsDeserializer.cs b/Capnp.Net.Runtime/ListOfBitsDeserializer.cs index 0e5ff07..226751c 100644 --- a/Capnp.Net.Runtime/ListOfBitsDeserializer.cs +++ b/Capnp.Net.Runtime/ListOfBitsDeserializer.cs @@ -11,8 +11,8 @@ namespace Capnp { readonly bool _defaultValue; - internal ListOfBitsDeserializer(ref DeserializerState context, bool defaultValue) : - base(ref context) + internal ListOfBitsDeserializer(in DeserializerState context, bool defaultValue) : + base(context) { _defaultValue = defaultValue; } diff --git a/Capnp.Net.Runtime/ListOfCapsDeserializer.cs b/Capnp.Net.Runtime/ListOfCapsDeserializer.cs index 22a9ac9..1339b2f 100644 --- a/Capnp.Net.Runtime/ListOfCapsDeserializer.cs +++ b/Capnp.Net.Runtime/ListOfCapsDeserializer.cs @@ -11,7 +11,7 @@ namespace Capnp public class ListOfCapsDeserializer : ListDeserializer, IReadOnlyList where T: class { - internal ListOfCapsDeserializer(ref DeserializerState state) : base(ref state) + internal ListOfCapsDeserializer(in DeserializerState state) : base(state) { Rpc.CapabilityReflection.ValidateCapabilityInterface(typeof(T)); } diff --git a/Capnp.Net.Runtime/ListOfEmptyDeserializer.cs b/Capnp.Net.Runtime/ListOfEmptyDeserializer.cs index 9b6ed42..b9b3d5a 100644 --- a/Capnp.Net.Runtime/ListOfEmptyDeserializer.cs +++ b/Capnp.Net.Runtime/ListOfEmptyDeserializer.cs @@ -10,8 +10,8 @@ namespace Capnp /// public class ListOfEmptyDeserializer : ListDeserializer, IReadOnlyList { - internal ListOfEmptyDeserializer(ref DeserializerState state) : - base(ref state) + internal ListOfEmptyDeserializer(in DeserializerState state) : + base(state) { } diff --git a/Capnp.Net.Runtime/ListOfPointersDeserializer.cs b/Capnp.Net.Runtime/ListOfPointersDeserializer.cs index 520e0e7..3611461 100644 --- a/Capnp.Net.Runtime/ListOfPointersDeserializer.cs +++ b/Capnp.Net.Runtime/ListOfPointersDeserializer.cs @@ -9,8 +9,8 @@ namespace Capnp /// public class ListOfPointersDeserializer: ListDeserializer, IReadOnlyList { - internal ListOfPointersDeserializer(ref DeserializerState state) : - base(ref state) + internal ListOfPointersDeserializer(in DeserializerState state) : + base(state) { } diff --git a/Capnp.Net.Runtime/ListOfPrimitivesDeserializer.cs b/Capnp.Net.Runtime/ListOfPrimitivesDeserializer.cs index 1cb357a..c2cae63 100644 --- a/Capnp.Net.Runtime/ListOfPrimitivesDeserializer.cs +++ b/Capnp.Net.Runtime/ListOfPrimitivesDeserializer.cs @@ -11,7 +11,7 @@ namespace Capnp /// /// List element type public class ListOfPrimitivesDeserializer: ListDeserializer, IReadOnlyList - where T: struct + where T: unmanaged { class ListOfULongAsStructView : IReadOnlyList { @@ -73,12 +73,10 @@ namespace Capnp readonly ListKind _kind; - internal ListOfPrimitivesDeserializer(ref DeserializerState state, ListKind kind) : - base(ref state) + internal ListOfPrimitivesDeserializer(in DeserializerState state, ListKind kind) : + base(state) { _kind = kind; - - var binCoder = PrimitiveCoder.Get(); } /// @@ -96,13 +94,12 @@ namespace Capnp /// is out of range. public T this[int index] => Data[index]; - ListOfPrimitivesDeserializer PrimitiveCast() where U: struct + ListOfPrimitivesDeserializer PrimitiveCast() where U: unmanaged { if (Marshal.SizeOf() != Marshal.SizeOf()) throw new NotSupportedException("Source and target types have different sizes, cannot cast"); - var stateCopy = State; - return new ListOfPrimitivesDeserializer(ref stateCopy, Kind); + return new ListOfPrimitivesDeserializer(State, Kind); } /// diff --git a/Capnp.Net.Runtime/ListOfStructsDeserializer.cs b/Capnp.Net.Runtime/ListOfStructsDeserializer.cs index 57794e3..03e6c91 100644 --- a/Capnp.Net.Runtime/ListOfStructsDeserializer.cs +++ b/Capnp.Net.Runtime/ListOfStructsDeserializer.cs @@ -9,8 +9,8 @@ namespace Capnp /// public class ListOfStructsDeserializer: ListDeserializer, IReadOnlyList { - internal ListOfStructsDeserializer(ref DeserializerState context): - base(ref context) + internal ListOfStructsDeserializer(in DeserializerState context): + base(context) { }