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.Threading; 21 using Grpc.Core; 22 using Grpc.Core.Internal; 23 using System.Collections.Generic; 24 using System.Diagnostics; 25 26 namespace Grpc.Microbenchmarks 27 { 28 public class SendMessageBenchmark 29 { 30 static readonly NativeMethods Native = NativeMethods.Get(); 31 32 GrpcEnvironment environment; 33 Init()34 public void Init() 35 { 36 Native.grpcsharp_test_override_method("grpcsharp_call_start_batch", "nop"); 37 environment = GrpcEnvironment.AddRef(); 38 } 39 Cleanup()40 public void Cleanup() 41 { 42 GrpcEnvironment.ReleaseAsync().Wait(); 43 // TODO(jtattermusch): track GC stats 44 } 45 Run(int threadCount, int iterations, int payloadSize)46 public void Run(int threadCount, int iterations, int payloadSize) 47 { 48 Console.WriteLine(string.Format("SendMessageBenchmark: threads={0}, iterations={1}, payloadSize={2}", threadCount, iterations, payloadSize)); 49 var threadedBenchmark = new ThreadedBenchmark(threadCount, () => ThreadBody(iterations, payloadSize)); 50 threadedBenchmark.Run(); 51 } 52 ThreadBody(int iterations, int payloadSize)53 private void ThreadBody(int iterations, int payloadSize) 54 { 55 var completionRegistry = new CompletionRegistry(environment, () => environment.BatchContextPool.Lease(), () => throw new NotImplementedException()); 56 var cq = CompletionQueueSafeHandle.CreateAsync(completionRegistry); 57 var call = CreateFakeCall(cq); 58 59 var sendCompletionCallback = new NopSendCompletionCallback(); 60 var payload = new byte[payloadSize]; 61 var writeFlags = default(WriteFlags); 62 63 var stopwatch = Stopwatch.StartNew(); 64 for (int i = 0; i < iterations; i++) 65 { 66 call.StartSendMessage(sendCompletionCallback, payload, writeFlags, false); 67 var callback = completionRegistry.Extract(completionRegistry.LastRegisteredKey); 68 callback.OnComplete(true); 69 } 70 stopwatch.Stop(); 71 Console.WriteLine("Elapsed millis: " + stopwatch.ElapsedMilliseconds); 72 73 cq.Dispose(); 74 } 75 CreateFakeCall(CompletionQueueSafeHandle cq)76 private static CallSafeHandle CreateFakeCall(CompletionQueueSafeHandle cq) 77 { 78 var call = CallSafeHandle.CreateFake(new IntPtr(0xdead), cq); 79 bool success = false; 80 while (!success) 81 { 82 // avoid calling destroy on a nonexistent grpc_call pointer 83 call.DangerousAddRef(ref success); 84 } 85 return call; 86 } 87 88 private class NopSendCompletionCallback : ISendCompletionCallback 89 { OnSendCompletion(bool success)90 public void OnSendCompletion(bool success) 91 { 92 // NOP 93 } 94 } 95 } 96 } 97