From c91bc02d979c30da40b67204324f28b569a3c8b6 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 19 May 2017 14:49:26 +0200 Subject: [PATCH 1/9] Add Grpc.Microbenchmarks project --- src/csharp/Grpc.Microbenchmarks/.gitignore | 2 + .../Grpc.Microbenchmarks.csproj | 28 ++++++++++++ src/csharp/Grpc.Microbenchmarks/Program.cs | 45 +++++++++++++++++++ src/csharp/Grpc.sln | 8 +++- 4 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 src/csharp/Grpc.Microbenchmarks/.gitignore create mode 100644 src/csharp/Grpc.Microbenchmarks/Grpc.Microbenchmarks.csproj create mode 100644 src/csharp/Grpc.Microbenchmarks/Program.cs diff --git a/src/csharp/Grpc.Microbenchmarks/.gitignore b/src/csharp/Grpc.Microbenchmarks/.gitignore new file mode 100644 index 0000000000000..1746e3269ed0f --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/.gitignore @@ -0,0 +1,2 @@ +bin +obj diff --git a/src/csharp/Grpc.Microbenchmarks/Grpc.Microbenchmarks.csproj b/src/csharp/Grpc.Microbenchmarks/Grpc.Microbenchmarks.csproj new file mode 100644 index 0000000000000..26a940e488785 --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/Grpc.Microbenchmarks.csproj @@ -0,0 +1,28 @@ + + + + + + + net45;netcoreapp1.0 + Grpc.Microbenchmarks + Exe + Grpc.Microbenchmarks + $(PackageTargetFallback);portable-net45 + 1.0.4 + + + + + + + + + + + + + + + + diff --git a/src/csharp/Grpc.Microbenchmarks/Program.cs b/src/csharp/Grpc.Microbenchmarks/Program.cs new file mode 100644 index 0000000000000..ac577d1b984ef --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/Program.cs @@ -0,0 +1,45 @@ +#region Copyright notice and license + +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; + +namespace Grpc.Microbenchmarks +{ + class Program + { + public static void Main(string[] args) + { + Console.WriteLine("Helloworld"); + } + } +} diff --git a/src/csharp/Grpc.sln b/src/csharp/Grpc.sln index beab3ccb36c48..d9a7b8d556b85 100644 --- a/src/csharp/Grpc.sln +++ b/src/csharp/Grpc.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26228.4 +VisualStudioVersion = 15.0.26430.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Core", "Grpc.Core\Grpc.Core.csproj", "{BD878CB3-BDB4-46AB-84EF-C3B4729F56BC}" EndProject @@ -37,6 +37,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Reflection", "Grpc.Ref EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Reflection.Tests", "Grpc.Reflection.Tests\Grpc.Reflection.Tests.csproj", "{335AD0A2-F2CC-4C2E-853C-26174206BEE7}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Microbenchmarks", "Grpc.Microbenchmarks\Grpc.Microbenchmarks.csproj", "{84C17746-4727-4290-8E8B-A380793DAE1E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -111,6 +113,10 @@ Global {335AD0A2-F2CC-4C2E-853C-26174206BEE7}.Debug|Any CPU.Build.0 = Debug|Any CPU {335AD0A2-F2CC-4C2E-853C-26174206BEE7}.Release|Any CPU.ActiveCfg = Release|Any CPU {335AD0A2-F2CC-4C2E-853C-26174206BEE7}.Release|Any CPU.Build.0 = Release|Any CPU + {84C17746-4727-4290-8E8B-A380793DAE1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {84C17746-4727-4290-8E8B-A380793DAE1E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {84C17746-4727-4290-8E8B-A380793DAE1E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {84C17746-4727-4290-8E8B-A380793DAE1E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From ff5f9d898f5ab2c49a0be09de33c8e2f80a6b785 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 19 May 2017 14:51:42 +0200 Subject: [PATCH 2/9] make internals visible to microbenchmarks --- src/csharp/Grpc.Core/Properties/AssemblyInfo.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs index 77ac347c7da4f..fe757820fd18c 100644 --- a/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs +++ b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs @@ -59,8 +59,14 @@ "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] +[assembly: InternalsVisibleTo("Grpc.Microbenchmarks,PublicKey=" + + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] #else [assembly: InternalsVisibleTo("Grpc.Core.Tests")] [assembly: InternalsVisibleTo("Grpc.Core.Testing")] [assembly: InternalsVisibleTo("Grpc.IntegrationTesting")] +[assembly: InternalsVisibleTo("Grpc.Microbenchmarks")] #endif From c7c2bf171414d577d0df336059ff5732b2c0ca4a Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 19 May 2017 15:01:43 +0200 Subject: [PATCH 3/9] add editorconfig for C# --- src/csharp/.editorconfig | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/csharp/.editorconfig diff --git a/src/csharp/.editorconfig b/src/csharp/.editorconfig new file mode 100644 index 0000000000000..7bc2bcce182b8 --- /dev/null +++ b/src/csharp/.editorconfig @@ -0,0 +1,7 @@ +root = true +[**] +end_of_line = LF +indent_style = space +indent_size = 4 +insert_final_newline = true +tab_width = 4 From 7cc83c8cd5772aff3033e4aafaa05cd2bdaa068a Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 19 May 2017 15:51:23 +0200 Subject: [PATCH 4/9] allow creating fake CallSafeHandle --- src/csharp/Grpc.Core/Internal/CallSafeHandle.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs index 8ed0c0b92f712..bc74e212b1960 100644 --- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs @@ -218,5 +218,16 @@ private static uint GetFlags(bool buffered) { return buffered ? 0 : GRPC_WRITE_BUFFER_HINT; } + + /// + /// Only for testing. + /// + public static CallSafeHandle CreateFake(IntPtr ptr, CompletionQueueSafeHandle cq) + { + var call = new CallSafeHandle(); + call.SetHandle(ptr); + call.Initialize(cq); + return call; + } } } From e58842f33a988c8691d1591c970b4b1232021432 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 19 May 2017 15:52:05 +0200 Subject: [PATCH 5/9] benchmark prototype --- .../Grpc.Core/Internal/CompletionRegistry.cs | 7 ++ src/csharp/Grpc.Microbenchmarks/Program.cs | 10 +- .../SendMessageBenchmark.cs | 106 ++++++++++++++++++ .../Grpc.Microbenchmarks/ThreadedBenchmark.cs | 79 +++++++++++++ 4 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs create mode 100644 src/csharp/Grpc.Microbenchmarks/ThreadedBenchmark.cs diff --git a/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs b/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs index a4aa8d3ffe42b..fc0ff72e6a100 100644 --- a/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs +++ b/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs @@ -52,6 +52,7 @@ internal class CompletionRegistry readonly GrpcEnvironment environment; readonly ConcurrentDictionary dict = new ConcurrentDictionary(new IntPtrComparer()); + IntPtr lastRegisteredKey; public CompletionRegistry(GrpcEnvironment environment) { @@ -62,6 +63,7 @@ public void Register(IntPtr key, OpCompletionDelegate callback) { environment.DebugStats.PendingBatchCompletions.Increment(); GrpcPreconditions.CheckState(dict.TryAdd(key, callback)); + this.lastRegisteredKey = key; } public void RegisterBatchCompletion(BatchContextSafeHandle ctx, BatchCompletionDelegate callback) @@ -84,6 +86,11 @@ public OpCompletionDelegate Extract(IntPtr key) return value; } + public IntPtr LastRegisteredKey + { + get { return this.lastRegisteredKey; } + } + private static void HandleBatchCompletion(bool success, BatchContextSafeHandle ctx, BatchCompletionDelegate callback) { try diff --git a/src/csharp/Grpc.Microbenchmarks/Program.cs b/src/csharp/Grpc.Microbenchmarks/Program.cs index ac577d1b984ef..09b6eb68d912c 100644 --- a/src/csharp/Grpc.Microbenchmarks/Program.cs +++ b/src/csharp/Grpc.Microbenchmarks/Program.cs @@ -32,6 +32,8 @@ #endregion using System; +using Grpc.Core; +using Grpc.Core.Internal; namespace Grpc.Microbenchmarks { @@ -39,7 +41,13 @@ class Program { public static void Main(string[] args) { - Console.WriteLine("Helloworld"); + var benchmark = new SendMessageBenchmark(); + benchmark.Init(); + foreach (int threadCount in new int[] {1, 1, 2, 4, 8, 12}) + { + benchmark.Run(threadCount, 4 * 1000 * 1000, 0); + } + benchmark.Cleanup(); } } } diff --git a/src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs b/src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs new file mode 100644 index 0000000000000..4575529bef659 --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs @@ -0,0 +1,106 @@ +#region Copyright notice and license + +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; +using System.Threading; +using Grpc.Core; +using Grpc.Core.Internal; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Grpc.Microbenchmarks +{ + public class SendMessageBenchmark + { + static readonly NativeMethods Native = NativeMethods.Get(); + + GrpcEnvironment environment; + + public void Init() + { + Native.grpcsharp_test_override_method("grpcsharp_call_start_batch", "nop"); + environment = GrpcEnvironment.AddRef(); + } + + public void Cleanup() + { + GrpcEnvironment.ReleaseAsync().Wait(); + // TODO(jtattermusch): track GC stats + } + + public void Run(int threadCount, int iterations, int payloadSize) + { + Console.WriteLine(string.Format("SendMessageBenchmark: threads={0}, iterations={1}, payloadSize={2}", threadCount, iterations, payloadSize)); + var threadedBenchmark = new ThreadedBenchmark(threadCount, () => ThreadBody(iterations, payloadSize)); + threadedBenchmark.Run(); + } + + private void ThreadBody(int iterations, int payloadSize) + { + // TODO(jtattermusch): parametrize by number of pending completions. + // TODO(jtattermusch): parametrize by cached/non-cached BatchContextSafeHandle + + var completionRegistry = new CompletionRegistry(environment); + var cq = CompletionQueueSafeHandle.CreateAsync(completionRegistry); + var call = CreateFakeCall(cq); + + var sendCompletionHandler = new SendCompletionHandler((success) => { }); + var payload = new byte[payloadSize]; + var writeFlags = default(WriteFlags); + + var stopwatch = Stopwatch.StartNew(); + for (int i = 0; i < iterations; i++) + { + call.StartSendMessage(sendCompletionHandler, payload, writeFlags, false); + var callback = completionRegistry.Extract(completionRegistry.LastRegisteredKey); + callback(); + } + stopwatch.Stop(); + Console.WriteLine("Elapsed millis: " + stopwatch.ElapsedMilliseconds); + + cq.Dispose(); + } + + private static CallSafeHandle CreateFakeCall(CompletionQueueSafeHandle cq) + { + var call = CallSafeHandle.CreateFake(new IntPtr(0xdead), cq); + bool success = false; + while (!success) + { + // avoid calling destroy on a nonexistent grpc_call pointer + call.DangerousAddRef(ref success); + } + return call; + } + } +} diff --git a/src/csharp/Grpc.Microbenchmarks/ThreadedBenchmark.cs b/src/csharp/Grpc.Microbenchmarks/ThreadedBenchmark.cs new file mode 100644 index 0000000000000..1c546240343b6 --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/ThreadedBenchmark.cs @@ -0,0 +1,79 @@ +#region Copyright notice and license + +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; +using System.Threading; +using Grpc.Core; +using Grpc.Core.Internal; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Grpc.Microbenchmarks +{ + public class ThreadedBenchmark + { + List runners; + + public ThreadedBenchmark(IEnumerable runners) + { + this.runners = new List(runners); + } + + public ThreadedBenchmark(int threadCount, Action threadBody) + { + this.runners = new List(); + for (int i = 0; i < threadCount; i++) + { + this.runners.Add(new ThreadStart(() => threadBody())); + } + } + + public void Run() + { + Console.WriteLine("Running threads."); + var threads = new List(); + for (int i = 0; i < runners.Count; i++) + { + var thread = new Thread(runners[i]); + thread.Start(); + threads.Add(thread); + } + + foreach (var thread in threads) + { + thread.Join(); + } + Console.WriteLine("All threads finished."); + } + } +} From 645ae74e88c73492ac3a98e5bf16ea24600e5a65 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 22 May 2017 08:46:26 -0700 Subject: [PATCH 6/9] overridable call_start_batch --- .../Grpc.Core/Internal/NativeMethods.cs | 4 ++ src/csharp/Grpc.Microbenchmarks/Program.cs | 2 + src/csharp/ext/grpc_csharp_ext.c | 65 +++++++++++++++---- 3 files changed, 60 insertions(+), 11 deletions(-) diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.cs index 696987d2a85c4..5ce792d296d96 100644 --- a/src/csharp/Grpc.Core/Internal/NativeMethods.cs +++ b/src/csharp/Grpc.Core/Internal/NativeMethods.cs @@ -164,6 +164,8 @@ internal class NativeMethods 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; + #endregion public NativeMethods(UnmanagedLibrary library) @@ -278,6 +280,7 @@ public NativeMethods(UnmanagedLibrary library) this.grpcsharp_test_callback = GetMethodDelegate(library); this.grpcsharp_test_nop = GetMethodDelegate(library); + this.grpcsharp_test_override_method = GetMethodDelegate(library); } /// @@ -434,6 +437,7 @@ public delegate void grpcsharp_channel_watch_connectivity_state_delegate(Channel public delegate CallError grpcsharp_test_callback_delegate([MarshalAs(UnmanagedType.FunctionPtr)] OpCompletionDelegate callback); public delegate IntPtr grpcsharp_test_nop_delegate(IntPtr ptr); + public delegate void grpcsharp_test_override_method(string methodName, string variant); } } } diff --git a/src/csharp/Grpc.Microbenchmarks/Program.cs b/src/csharp/Grpc.Microbenchmarks/Program.cs index 09b6eb68d912c..a0ca1f75ae66e 100644 --- a/src/csharp/Grpc.Microbenchmarks/Program.cs +++ b/src/csharp/Grpc.Microbenchmarks/Program.cs @@ -34,6 +34,7 @@ using System; using Grpc.Core; using Grpc.Core.Internal; +using Grpc.Core.Logging; namespace Grpc.Microbenchmarks { @@ -41,6 +42,7 @@ class Program { public static void Main(string[] args) { + GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error)); var benchmark = new SendMessageBenchmark(); benchmark.Init(); foreach (int threadCount in new int[] {1, 1, 2, 4, 8, 12}) diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index f6cff454bdba5..34f8b928ddf3d 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -529,6 +529,31 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_call_destroy(grpc_call *call) { grpc_call_unref(call); } +typedef grpc_call_error (*grpcsharp_call_start_batch_func) ( + grpc_call *call, const grpc_op *ops, size_t nops, + void *tag, void *reserved); + +/* Only for testing */ +static grpc_call_error grpcsharp_call_start_batch_nop( + grpc_call *call, const grpc_op *ops, size_t nops, + void *tag, void *reserved) { + return GRPC_CALL_OK; +} + +static grpc_call_error grpcsharp_call_start_batch_default( + grpc_call *call, const grpc_op *ops, size_t nops, + void *tag, void *reserved) { + return grpc_call_start_batch(call, ops, nops, tag, reserved); +} + +static grpcsharp_call_start_batch_func g_call_start_batch_func = grpcsharp_call_start_batch_default; + +static grpc_call_error grpcsharp_call_start_batch( + grpc_call *call, const grpc_op *ops, size_t nops, + void *tag, void *reserved) { + return g_call_start_batch_func(call, ops, nops, tag, reserved); +} + GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_unary( grpc_call *call, grpcsharp_batch_context *ctx, const char *send_buffer, size_t send_buffer_len, uint32_t write_flags, @@ -576,7 +601,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_unary( ops[5].flags = 0; ops[5].reserved = NULL; - return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } @@ -616,7 +641,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_client_streaming( ops[3].flags = 0; ops[3].reserved = NULL; - return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } @@ -656,7 +681,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming( ops[3].flags = 0; ops[3].reserved = NULL; - return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } @@ -685,7 +710,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_duplex_streaming( ops[1].flags = 0; ops[1].reserved = NULL; - return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } @@ -699,7 +724,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_recv_initial_metadata( ops[0].flags = 0; ops[0].reserved = NULL; - return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } @@ -720,7 +745,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_message( ops[1].flags = 0; ops[1].reserved = NULL; - return grpc_call_start_batch(call, ops, nops, ctx, NULL); + return grpcsharp_call_start_batch(call, ops, nops, ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_close_from_client( @@ -731,7 +756,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_close_from_client( ops[0].flags = 0; ops[0].reserved = NULL; - return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } @@ -773,7 +798,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_status_from_server( ops[nops].reserved = NULL; nops++; } - return grpc_call_start_batch(call, ops, nops, ctx, NULL); + return grpcsharp_call_start_batch(call, ops, nops, ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE @@ -784,7 +809,7 @@ grpcsharp_call_recv_message(grpc_call *call, grpcsharp_batch_context *ctx) { ops[0].data.recv_message.recv_message = &(ctx->recv_message); ops[0].flags = 0; ops[0].reserved = NULL; - return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } @@ -798,7 +823,7 @@ grpcsharp_call_start_serverside(grpc_call *call, grpcsharp_batch_context *ctx) { ops[0].flags = 0; ops[0].reserved = NULL; - return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } @@ -817,7 +842,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_initial_metadata( ops[0].flags = 0; ops[0].reserved = NULL; - return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } @@ -1092,3 +1117,21 @@ GPR_EXPORT void *GPR_CALLTYPE grpcsharp_test_nop(void *ptr) { return ptr; } GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_sizeof_grpc_event(void) { return sizeof(grpc_event); } + +/* Override a method for testing */ +GPR_EXPORT void GPR_CALLTYPE grpcsharp_test_override_method(const char *method_name, + const char *variant) { + if (strcmp("grpcsharp_call_start_batch", method_name) == 0) + { + if (strcmp("nop", variant) == 0) + { + g_call_start_batch_func = grpcsharp_call_start_batch_nop; + } else { + GPR_ASSERT(0); + } + } else { + GPR_ASSERT(0); + } +} + + From 7c206f4c154c0897898042060cf0be481995e131 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 22 May 2017 09:23:18 -0700 Subject: [PATCH 7/9] override in benchmark --- src/csharp/Grpc.Core/Internal/NativeMethods.cs | 2 +- src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.cs index 5ce792d296d96..e703e3e6cee27 100644 --- a/src/csharp/Grpc.Core/Internal/NativeMethods.cs +++ b/src/csharp/Grpc.Core/Internal/NativeMethods.cs @@ -437,7 +437,7 @@ public delegate void grpcsharp_channel_watch_connectivity_state_delegate(Channel public delegate CallError grpcsharp_test_callback_delegate([MarshalAs(UnmanagedType.FunctionPtr)] OpCompletionDelegate callback); public delegate IntPtr grpcsharp_test_nop_delegate(IntPtr ptr); - public delegate void grpcsharp_test_override_method(string methodName, string variant); + public delegate void grpcsharp_test_override_method_delegate(string methodName, string variant); } } } diff --git a/src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs b/src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs index 4575529bef659..eea375824f3b5 100644 --- a/src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs +++ b/src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs @@ -83,7 +83,7 @@ private void ThreadBody(int iterations, int payloadSize) { call.StartSendMessage(sendCompletionHandler, payload, writeFlags, false); var callback = completionRegistry.Extract(completionRegistry.LastRegisteredKey); - callback(); + callback(true); } stopwatch.Stop(); Console.WriteLine("Elapsed millis: " + stopwatch.ElapsedMilliseconds); From 254ab4c085ae39c0935b06edccfffdaeaeda94a1 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 23 May 2017 18:07:17 +0200 Subject: [PATCH 8/9] clang format code --- src/csharp/ext/grpc_csharp_ext.c | 81 +++++++++++++++++--------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index 34f8b928ddf3d..a56113eca3c40 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -529,28 +529,35 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_call_destroy(grpc_call *call) { grpc_call_unref(call); } -typedef grpc_call_error (*grpcsharp_call_start_batch_func) ( - grpc_call *call, const grpc_op *ops, size_t nops, - void *tag, void *reserved); +typedef grpc_call_error (*grpcsharp_call_start_batch_func)(grpc_call *call, + const grpc_op *ops, + size_t nops, + void *tag, + void *reserved); /* Only for testing */ -static grpc_call_error grpcsharp_call_start_batch_nop( - grpc_call *call, const grpc_op *ops, size_t nops, - void *tag, void *reserved) { +static grpc_call_error grpcsharp_call_start_batch_nop(grpc_call *call, + const grpc_op *ops, + size_t nops, void *tag, + void *reserved) { return GRPC_CALL_OK; } -static grpc_call_error grpcsharp_call_start_batch_default( - grpc_call *call, const grpc_op *ops, size_t nops, - void *tag, void *reserved) { +static grpc_call_error grpcsharp_call_start_batch_default(grpc_call *call, + const grpc_op *ops, + size_t nops, + void *tag, + void *reserved) { return grpc_call_start_batch(call, ops, nops, tag, reserved); } -static grpcsharp_call_start_batch_func g_call_start_batch_func = grpcsharp_call_start_batch_default; +static grpcsharp_call_start_batch_func g_call_start_batch_func = + grpcsharp_call_start_batch_default; -static grpc_call_error grpcsharp_call_start_batch( - grpc_call *call, const grpc_op *ops, size_t nops, - void *tag, void *reserved) { +static grpc_call_error grpcsharp_call_start_batch(grpc_call *call, + const grpc_op *ops, + size_t nops, void *tag, + void *reserved) { return g_call_start_batch_func(call, ops, nops, tag, reserved); } @@ -601,8 +608,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_unary( ops[5].flags = 0; ops[5].reserved = NULL; - return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, - NULL); + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), + ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_client_streaming( @@ -641,8 +648,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_client_streaming( ops[3].flags = 0; ops[3].reserved = NULL; - return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, - NULL); + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), + ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming( @@ -681,8 +688,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming( ops[3].flags = 0; ops[3].reserved = NULL; - return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, - NULL); + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), + ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_duplex_streaming( @@ -710,8 +717,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_duplex_streaming( ops[1].flags = 0; ops[1].reserved = NULL; - return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, - NULL); + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), + ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_recv_initial_metadata( @@ -724,8 +731,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_recv_initial_metadata( ops[0].flags = 0; ops[0].reserved = NULL; - return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, - NULL); + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), + ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_message( @@ -756,8 +763,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_close_from_client( ops[0].flags = 0; ops[0].reserved = NULL; - return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, - NULL); + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), + ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_status_from_server( @@ -809,8 +816,8 @@ grpcsharp_call_recv_message(grpc_call *call, grpcsharp_batch_context *ctx) { ops[0].data.recv_message.recv_message = &(ctx->recv_message); ops[0].flags = 0; ops[0].reserved = NULL; - return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, - NULL); + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), + ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE @@ -823,8 +830,8 @@ grpcsharp_call_start_serverside(grpc_call *call, grpcsharp_batch_context *ctx) { ops[0].flags = 0; ops[0].reserved = NULL; - return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, - NULL); + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), + ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_initial_metadata( @@ -842,8 +849,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_initial_metadata( ops[0].flags = 0; ops[0].reserved = NULL; - return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, - NULL); + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), + ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE @@ -1119,12 +1126,10 @@ GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_sizeof_grpc_event(void) { } /* Override a method for testing */ -GPR_EXPORT void GPR_CALLTYPE grpcsharp_test_override_method(const char *method_name, - const char *variant) { - if (strcmp("grpcsharp_call_start_batch", method_name) == 0) - { - if (strcmp("nop", variant) == 0) - { +GPR_EXPORT void GPR_CALLTYPE +grpcsharp_test_override_method(const char *method_name, const char *variant) { + if (strcmp("grpcsharp_call_start_batch", method_name) == 0) { + if (strcmp("nop", variant) == 0) { g_call_start_batch_func = grpcsharp_call_start_batch_nop; } else { GPR_ASSERT(0); @@ -1133,5 +1138,3 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_test_override_method(const char *method_n GPR_ASSERT(0); } } - - From c400cc5f8dcff7ff70a7030f085ebdd5c9359fa5 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 26 May 2017 14:44:34 -0700 Subject: [PATCH 9/9] address comments --- src/csharp/Grpc.Core/Internal/CompletionRegistry.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs b/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs index fc0ff72e6a100..075286d33ea9c 100644 --- a/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs +++ b/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs @@ -52,7 +52,7 @@ internal class CompletionRegistry readonly GrpcEnvironment environment; readonly ConcurrentDictionary dict = new ConcurrentDictionary(new IntPtrComparer()); - IntPtr lastRegisteredKey; + IntPtr lastRegisteredKey; // only for testing public CompletionRegistry(GrpcEnvironment environment) { @@ -86,6 +86,9 @@ public OpCompletionDelegate Extract(IntPtr key) return value; } + /// + /// For testing purposes only. + /// public IntPtr LastRegisteredKey { get { return this.lastRegisteredKey; }