mirror of https://github.com/grpc/grpc.git
Merge pull request #722 from jtattermusch/csharp_performance
Added support for true synchronous unary call & some performance tests.pull/785/head
commit
517aa0c535
14 changed files with 364 additions and 26 deletions
@ -0,0 +1,145 @@ |
||||
#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.Diagnostics; |
||||
using System.Threading; |
||||
using System.Threading.Tasks; |
||||
using Grpc.Core; |
||||
using Grpc.Core.Internal; |
||||
using Grpc.Core.Utils; |
||||
using NUnit.Framework; |
||||
using System.Runtime.InteropServices; |
||||
|
||||
namespace Grpc.Core.Tests |
||||
{ |
||||
public class PInvokeTest |
||||
{ |
||||
int counter; |
||||
|
||||
[DllImport("grpc_csharp_ext.dll")] |
||||
static extern GRPCCallError grpcsharp_test_callback([MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback); |
||||
|
||||
[DllImport("grpc_csharp_ext.dll")] |
||||
static extern IntPtr grpcsharp_test_nop(IntPtr ptr); |
||||
|
||||
[TestFixtureSetUp] |
||||
public void Init() |
||||
{ |
||||
GrpcEnvironment.Initialize(); |
||||
} |
||||
|
||||
[TestFixtureTearDown] |
||||
public void Cleanup() |
||||
{ |
||||
GrpcEnvironment.Shutdown(); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// (~1.26us .NET Windows) |
||||
/// </summary> |
||||
[Test] |
||||
public void CompletionQueueCreateDestroyBenchmark() |
||||
{ |
||||
BenchmarkUtil.RunBenchmark( |
||||
100000, 1000000, |
||||
() => { |
||||
CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create(); |
||||
cq.Dispose(); |
||||
} |
||||
); |
||||
} |
||||
|
||||
|
||||
/// <summary> |
||||
/// Approximate results: |
||||
/// (~80ns Mono Linux) |
||||
/// (~110ns .NET Windows) |
||||
/// </summary> |
||||
[Test] |
||||
public void NativeCallbackBenchmark() |
||||
{ |
||||
CompletionCallbackDelegate handler = Handler; |
||||
|
||||
counter = 0; |
||||
BenchmarkUtil.RunBenchmark( |
||||
1000000, 10000000, |
||||
() => { |
||||
grpcsharp_test_callback(handler); |
||||
} |
||||
); |
||||
Assert.AreNotEqual(0, counter); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Creating a new native-to-managed callback has significant overhead |
||||
/// compared to using an existing one. We need to be aware of this. |
||||
/// (~50us on Mono Linux!!!) |
||||
/// (~1.1us on .NET Windows) |
||||
/// </summary> |
||||
[Test] |
||||
public void NewNativeCallbackBenchmark() |
||||
{ |
||||
counter = 0; |
||||
BenchmarkUtil.RunBenchmark( |
||||
10000, 10000, |
||||
() => { |
||||
grpcsharp_test_callback(new CompletionCallbackDelegate(Handler)); |
||||
} |
||||
); |
||||
Assert.AreNotEqual(0, counter); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Tests overhead of a simple PInvoke call. |
||||
/// (~46ns .NET Windows) |
||||
/// </summary> |
||||
[Test] |
||||
public void NopPInvokeBenchmark() |
||||
{ |
||||
CompletionCallbackDelegate handler = Handler; |
||||
|
||||
BenchmarkUtil.RunBenchmark( |
||||
1000000, 100000000, |
||||
() => { |
||||
grpcsharp_test_nop(IntPtr.Zero); |
||||
} |
||||
); |
||||
} |
||||
|
||||
private void Handler(GRPCOpError op, IntPtr ptr) { |
||||
counter ++; |
||||
} |
||||
} |
||||
} |
||||
|
@ -0,0 +1,68 @@ |
||||
#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.Tasks; |
||||
using System.Collections.Generic; |
||||
using System.Collections.Concurrent; |
||||
using System.Diagnostics; |
||||
|
||||
namespace Grpc.Core.Utils |
||||
{ |
||||
public static class BenchmarkUtil |
||||
{ |
||||
/// <summary> |
||||
/// Runs a simple benchmark preceded by warmup phase. |
||||
/// </summary> |
||||
public static void RunBenchmark(int warmupIterations, int benchmarkIterations, Action action) |
||||
{ |
||||
Console.WriteLine("Warmup iterations: " + warmupIterations); |
||||
for (int i = 0; i < warmupIterations; i++) |
||||
{ |
||||
action(); |
||||
} |
||||
|
||||
Console.WriteLine("Benchmark iterations: " + benchmarkIterations); |
||||
var stopwatch = new Stopwatch(); |
||||
stopwatch.Start(); |
||||
for (int i = 0; i < benchmarkIterations; i++) |
||||
{ |
||||
action(); |
||||
} |
||||
stopwatch.Stop(); |
||||
Console.WriteLine("Elapsed time: " + stopwatch.ElapsedMilliseconds + "ms"); |
||||
Console.WriteLine("Ops per second: " + (int) ((double) benchmarkIterations * 1000 / stopwatch.ElapsedMilliseconds)); |
||||
} |
||||
} |
||||
} |
||||
|
@ -0,0 +1,57 @@ |
||||
#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.Core.Utils |
||||
{ |
||||
public static class ExceptionHelper |
||||
{ |
||||
/// <summary> |
||||
/// If inner exceptions contain RpcException, rethrows it. |
||||
/// Otherwise, rethrows the original aggregate exception. |
||||
/// Always throws, the exception return type is here only to make the. |
||||
/// </summary> |
||||
public static Exception UnwrapRpcException(AggregateException ae) { |
||||
foreach (var e in ae.InnerExceptions) |
||||
{ |
||||
if (e is RpcException) |
||||
{ |
||||
throw e; |
||||
} |
||||
} |
||||
throw ae; |
||||
} |
||||
} |
||||
} |
||||
|
Loading…
Reference in new issue