From dd5f19765ea382b6ae1b08b786c448c923597a5c Mon Sep 17 00:00:00 2001 From: mgravell Date: Tue, 2 Jul 2019 09:11:14 +0100 Subject: [PATCH] add framework overhead "PingBenchmark" --- .../Grpc.Microbenchmarks/PingBenchmark.cs | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/csharp/Grpc.Microbenchmarks/PingBenchmark.cs diff --git a/src/csharp/Grpc.Microbenchmarks/PingBenchmark.cs b/src/csharp/Grpc.Microbenchmarks/PingBenchmark.cs new file mode 100644 index 00000000000..25996fb6868 --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/PingBenchmark.cs @@ -0,0 +1,84 @@ +using System.Threading.Tasks; +using BenchmarkDotNet.Attributes; +using Grpc.Core; + +namespace Grpc.Microbenchmarks +{ + // this test creates a real server and client, measuring the inherent inbuilt + // platform overheads; the marshallers **DO NOT ALLOCATE**, so any allocations + // are from the framework, not the messages themselves + + // important: allocs are not reliable on .NET Core until .NET Core 3, since + // this test involves multiple threads + + [ClrJob, CoreJob] // test .NET Core and .NET Framework + [MemoryDiagnoser] // allocations + public class PingBenchmark + { + private static readonly Task CompletedString = Task.FromResult(""); + private static readonly byte[] EmptyBlob = new byte[0]; + private static readonly Marshaller EmptyMarshaller = new Marshaller(_ => EmptyBlob, _ => ""); + private static readonly Method PingMethod = new Method(MethodType.Unary, nameof(PingBenchmark), "Ping", EmptyMarshaller, EmptyMarshaller); + + + [Benchmark] + public async ValueTask PingAsync() + { + using (var result = client.PingAsync("")) + { + return await result.ResponseAsync; + } + } + + [Benchmark] + public string Ping() + { + return client.Ping(""); + } + + private Task ServerMethod(string request, ServerCallContext context) + { + return CompletedString; + } + + Server server; + Channel channel; + PingClient client; + + [GlobalSetup] + public async Task Setup() + { + // create server + server = new Server { + Ports = { new ServerPort("localhost", 10042, ServerCredentials.Insecure) }, + Services = { ServerServiceDefinition.CreateBuilder().AddMethod(PingMethod, ServerMethod).Build() }, + }; + server.Start(); + + // create client + channel = new Channel("localhost", 10042, ChannelCredentials.Insecure); + await channel.ConnectAsync(); + client = new PingClient(new DefaultCallInvoker(channel)); + } + + [GlobalCleanup] + public async Task Cleanup() + { + await channel.ShutdownAsync(); + await server.ShutdownAsync(); + } + + class PingClient : LiteClientBase + { + public PingClient(CallInvoker callInvoker) : base(callInvoker) { } + public AsyncUnaryCall PingAsync(string request, CallOptions options = default) + { + return CallInvoker.AsyncUnaryCall(PingMethod, null, options, request); + } + public string Ping(string request, CallOptions options = default) + { + return CallInvoker.BlockingUnaryCall(PingMethod, null, options, request); + } + } + } +}