Merge pull request #19720 from jtattermusch/csharp_unary_overhead_microbenchmark

C# Microbenchmark: Unary call overhead
pull/19685/head
Jan Tattermusch 6 years ago committed by GitHub
commit cc291c4a65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs
  2. 90
      src/csharp/Grpc.Microbenchmarks/UnaryCallOverheadBenchmark.cs
  3. 20
      src/csharp/ext/grpc_csharp_ext.c
  4. 4
      src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core/runtimes/grpc_csharp_ext_dummy_stubs.c
  5. 1
      templates/src/csharp/Grpc.Core/Internal/native_methods.include

@ -130,6 +130,7 @@ namespace Grpc.Core.Internal
public readonly Delegates.grpcsharp_test_callback_delegate grpcsharp_test_callback;
public readonly Delegates.grpcsharp_test_nop_delegate grpcsharp_test_nop;
public readonly Delegates.grpcsharp_test_override_method_delegate grpcsharp_test_override_method;
public readonly Delegates.grpcsharp_test_call_start_unary_echo_delegate grpcsharp_test_call_start_unary_echo;
#endregion
@ -231,6 +232,7 @@ namespace Grpc.Core.Internal
this.grpcsharp_test_callback = GetMethodDelegate<Delegates.grpcsharp_test_callback_delegate>(library);
this.grpcsharp_test_nop = GetMethodDelegate<Delegates.grpcsharp_test_nop_delegate>(library);
this.grpcsharp_test_override_method = GetMethodDelegate<Delegates.grpcsharp_test_override_method_delegate>(library);
this.grpcsharp_test_call_start_unary_echo = GetMethodDelegate<Delegates.grpcsharp_test_call_start_unary_echo_delegate>(library);
}
public NativeMethods(DllImportsFromStaticLib unusedInstance)
@ -331,6 +333,7 @@ namespace Grpc.Core.Internal
this.grpcsharp_test_callback = DllImportsFromStaticLib.grpcsharp_test_callback;
this.grpcsharp_test_nop = DllImportsFromStaticLib.grpcsharp_test_nop;
this.grpcsharp_test_override_method = DllImportsFromStaticLib.grpcsharp_test_override_method;
this.grpcsharp_test_call_start_unary_echo = DllImportsFromStaticLib.grpcsharp_test_call_start_unary_echo;
}
public NativeMethods(DllImportsFromSharedLib unusedInstance)
@ -431,6 +434,7 @@ namespace Grpc.Core.Internal
this.grpcsharp_test_callback = DllImportsFromSharedLib.grpcsharp_test_callback;
this.grpcsharp_test_nop = DllImportsFromSharedLib.grpcsharp_test_nop;
this.grpcsharp_test_override_method = DllImportsFromSharedLib.grpcsharp_test_override_method;
this.grpcsharp_test_call_start_unary_echo = DllImportsFromSharedLib.grpcsharp_test_call_start_unary_echo;
}
/// <summary>
@ -534,6 +538,7 @@ namespace Grpc.Core.Internal
public delegate CallError grpcsharp_test_callback_delegate([MarshalAs(UnmanagedType.FunctionPtr)] NativeCallbackTestDelegate callback);
public delegate IntPtr grpcsharp_test_nop_delegate(IntPtr ptr);
public delegate void grpcsharp_test_override_method_delegate(string methodName, string variant);
public delegate CallError grpcsharp_test_call_start_unary_echo_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags);
}
/// <summary>
@ -830,6 +835,9 @@ namespace Grpc.Core.Internal
[DllImport(ImportName)]
public static extern void grpcsharp_test_override_method(string methodName, string variant);
[DllImport(ImportName)]
public static extern CallError grpcsharp_test_call_start_unary_echo(CallSafeHandle call, BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags);
}
/// <summary>
@ -1126,6 +1134,9 @@ namespace Grpc.Core.Internal
[DllImport(ImportName)]
public static extern void grpcsharp_test_override_method(string methodName, string variant);
[DllImport(ImportName)]
public static extern CallError grpcsharp_test_call_start_unary_echo(CallSafeHandle call, BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags);
}
}
}

@ -0,0 +1,90 @@
#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 measures the overhead of C# wrapping layer when invoking calls;
// the marshallers **DO NOT ALLOCATE**, so any allocations
// are from the framework, not the messages themselves
[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 SyncUnaryCallOverhead()
{
return client.Ping("", new CallOptions());
}
Channel channel;
PingClient client;
[GlobalSetup]
public void Setup()
{
// create client, the channel will actually never connect because call logic will be short-circuited
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);
}
}
}
}

@ -632,6 +632,26 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_unary(
ctx, NULL);
}
/* Only for testing. Shortcircuits the unary call logic and only echoes the
message as if it was received from the server */
GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_test_call_start_unary_echo(
grpc_call* call, grpcsharp_batch_context* ctx, const char* send_buffer,
size_t send_buffer_len, uint32_t write_flags,
grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
// prepare as if we were performing a normal RPC.
grpc_byte_buffer* send_message =
string_to_byte_buffer(send_buffer, send_buffer_len);
ctx->recv_message = send_message; // echo message sent by the client as if
// received from server.
ctx->recv_status_on_client.status = GRPC_STATUS_OK;
ctx->recv_status_on_client.status_details = grpc_empty_slice();
// echo initial metadata as if received from server (as trailing metadata)
grpcsharp_metadata_array_move(&(ctx->recv_status_on_client.trailing_metadata),
initial_metadata);
return GRPC_CALL_OK;
}
GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_client_streaming(
grpc_call* call, grpcsharp_batch_context* ctx,
grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {

@ -406,3 +406,7 @@ void grpcsharp_test_override_method() {
fprintf(stderr, "Should never reach here");
abort();
}
void grpcsharp_test_call_start_unary_echo() {
fprintf(stderr, "Should never reach here");
abort();
}

@ -96,6 +96,7 @@ native_method_signatures = [
'CallError grpcsharp_test_callback([MarshalAs(UnmanagedType.FunctionPtr)] NativeCallbackTestDelegate callback)',
'IntPtr grpcsharp_test_nop(IntPtr ptr)',
'void grpcsharp_test_override_method(string methodName, string variant)',
'CallError grpcsharp_test_call_start_unary_echo(CallSafeHandle call, BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags)',
]
import re

Loading…
Cancel
Save