blob: cbcf5d361caa1b9f26ae871223094c4995ac50b5 [file] [log] [blame]
#region Copyright notice and license
// Copyright 2019 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion
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<string> CompletedString = Task.FromResult("");
private static readonly byte[] EmptyBlob = new byte[0];
private static readonly Marshaller<string> EmptyMarshaller = new Marshaller<string>(_ => EmptyBlob, _ => "");
private static readonly Method<string, string> PingMethod = new Method<string, string>(MethodType.Unary, nameof(PingBenchmark), "Ping", EmptyMarshaller, EmptyMarshaller);
[Benchmark]
public async ValueTask<string> PingAsync()
{
using (var result = client.PingAsync("", new CallOptions()))
{
return await result.ResponseAsync;
}
}
[Benchmark]
public string Ping()
{
return client.Ping("", new CallOptions());
}
private Task<string> 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 : ClientBase
{
public PingClient(CallInvoker callInvoker) : base(callInvoker) { }
public AsyncUnaryCall<string> PingAsync(string request, CallOptions options)
{
return CallInvoker.AsyncUnaryCall(PingMethod, null, options, request);
}
public string Ping(string request, CallOptions options)
{
return CallInvoker.BlockingUnaryCall(PingMethod, null, options, request);
}
}
}
}