Skip to content

Commit

Permalink
add unary call overhead benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
jtattermusch committed Jul 23, 2019
1 parent 1650d6a commit 34dfa06
Showing 1 changed file with 93 additions and 0 deletions.
93 changes: 93 additions & 0 deletions src/csharp/Grpc.Microbenchmarks/UnaryCallOverheadBenchmark.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#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;
using Grpc.Core.Internal;
using System;

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 UnaryCallOverheadBenchmark
{
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 string Ping()
{
return client.Ping("", new CallOptions());
}

Channel channel;
PingClient client;

[GlobalSetup]
public void Setup()
{
// create client
channel = new Channel("localhost", 10042, ChannelCredentials.Insecure);
client = new PingClient(new DefaultCallInvoker(channel));

var native = NativeMethods.Get();

// replace the implementation of a native method with a fake
NativeMethods.Delegates.grpcsharp_call_start_unary_delegate fakeCallStartUnary = (CallSafeHandle call, BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags) => {
return native.grpcsharp_test_call_start_unary_echo(call, ctx, sendBuffer, sendBufferLen, writeFlags, metadataArray, metadataFlags);
};
native.GetType().GetField(nameof(native.grpcsharp_call_start_unary)).SetValue(native, fakeCallStartUnary);

NativeMethods.Delegates.grpcsharp_completion_queue_pluck_delegate fakeCqPluck = (CompletionQueueSafeHandle cq, IntPtr tag) => {
return new CompletionQueueEvent {
type = CompletionQueueEvent.CompletionType.OpComplete,
success = 1,
tag = tag
};
};
native.GetType().GetField(nameof(native.grpcsharp_completion_queue_pluck)).SetValue(native, fakeCqPluck);
}

[GlobalCleanup]
public async Task Cleanup()
{
await channel.ShutdownAsync();
}

class PingClient : LiteClientBase
{
public PingClient(CallInvoker callInvoker) : base(callInvoker) { }

public string Ping(string request, CallOptions options)
{
return CallInvoker.BlockingUnaryCall(PingMethod, null, options, request);
}
}
}
}

0 comments on commit 34dfa06

Please sign in to comment.