1 #region Copyright notice and license 2 3 // Copyright 2015 gRPC authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 #endregion 18 19 using System; 20 using System.Diagnostics; 21 using System.Runtime.InteropServices; 22 using System.Threading; 23 using System.Threading.Tasks; 24 using Grpc.Core; 25 using Grpc.Core.Internal; 26 using Grpc.Core.Utils; 27 using NUnit.Framework; 28 29 namespace Grpc.Core.Tests 30 { 31 public class PInvokeTest 32 { 33 static readonly NativeMethods Native = NativeMethods.Get(); 34 35 int counter; 36 37 /// <summary> 38 /// (~1.26us .NET Windows) 39 /// </summary> 40 [Test] CompletionQueueCreateSyncDestroyBenchmark()41 public void CompletionQueueCreateSyncDestroyBenchmark() 42 { 43 GrpcEnvironment.AddRef(); // completion queue requires gRPC environment being initialized. 44 45 BenchmarkUtil.RunBenchmark( 46 10, 10, 47 () => 48 { 49 CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.CreateSync(); 50 cq.Dispose(); 51 }); 52 53 GrpcEnvironment.ReleaseAsync().Wait(); 54 } 55 56 /// <summary> 57 /// Approximate results: 58 /// (~80ns Mono Linux) 59 /// (~110ns .NET Windows) 60 /// </summary> 61 [Test] 62 [Category("Performance")] 63 [Ignore("Prevent running on Jenkins")] NativeCallbackBenchmark()64 public void NativeCallbackBenchmark() 65 { 66 NativeCallbackTestDelegate handler = Handler; 67 68 counter = 0; 69 BenchmarkUtil.RunBenchmark( 70 1000000, 10000000, 71 () => 72 { 73 Native.grpcsharp_test_callback(handler); 74 }); 75 Assert.AreNotEqual(0, counter); 76 } 77 78 /// <summary> 79 /// Creating a new native-to-managed callback has significant overhead 80 /// compared to using an existing one. We need to be aware of this. 81 /// (~50us on Mono Linux!!!) 82 /// (~1.1us on .NET Windows) 83 /// </summary> 84 [Test] 85 [Category("Performance")] 86 [Ignore("Prevent running on Jenkins")] NewNativeCallbackBenchmark()87 public void NewNativeCallbackBenchmark() 88 { 89 counter = 0; 90 BenchmarkUtil.RunBenchmark( 91 10000, 10000, 92 () => 93 { 94 Native.grpcsharp_test_callback(new NativeCallbackTestDelegate(Handler)); 95 }); 96 Assert.AreNotEqual(0, counter); 97 } 98 99 /// <summary> 100 /// Tests overhead of a simple PInvoke call. 101 /// (~46ns .NET Windows) 102 /// </summary> 103 [Test] 104 [Category("Performance")] 105 [Ignore("Prevent running on Jenkins")] NopPInvokeBenchmark()106 public void NopPInvokeBenchmark() 107 { 108 BenchmarkUtil.RunBenchmark( 109 1000000, 100000000, 110 () => 111 { 112 Native.grpcsharp_test_nop(IntPtr.Zero); 113 }); 114 } 115 Handler(bool success)116 private void Handler(bool success) 117 { 118 counter++; 119 } 120 } 121 } 122