UnaryCallOverheadBenchmark.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #region Copyright notice and license
  2. // Copyright 2019 The gRPC Authors
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. #endregion
  16. using System.Threading.Tasks;
  17. using BenchmarkDotNet.Attributes;
  18. using Grpc.Core;
  19. using Grpc.Core.Internal;
  20. using System;
  21. namespace Grpc.Microbenchmarks
  22. {
  23. // this test measures the overhead of C# wrapping layer when invoking calls;
  24. // the marshallers **DO NOT ALLOCATE**, so any allocations
  25. // are from the framework, not the messages themselves
  26. [ClrJob, CoreJob] // test .NET Core and .NET Framework
  27. [MemoryDiagnoser] // allocations
  28. public class UnaryCallOverheadBenchmark
  29. {
  30. private static readonly Task<string> CompletedString = Task.FromResult("");
  31. private static readonly Marshaller<byte[]> IdentityMarshaller = new Marshaller<byte[]>(msg => msg, payload => payload);
  32. private static readonly Method<byte[], byte[]> PingMethod = new Method<byte[], byte[]>(MethodType.Unary, nameof(PingBenchmark), "Ping", IdentityMarshaller, IdentityMarshaller);
  33. private int payloadSize;
  34. private byte[] payload;
  35. // size of payload that is sent as request and received as response.
  36. [Params(0, 1, 10, 100, 1000)]
  37. public int PayloadSize
  38. {
  39. get { return payloadSize; }
  40. set
  41. {
  42. payloadSize = value;
  43. payload = new byte[value];
  44. }
  45. }
  46. [Benchmark]
  47. public byte[] SyncUnaryCallOverhead()
  48. {
  49. return client.Ping(payload, new CallOptions());
  50. }
  51. Channel channel;
  52. PingClient client;
  53. [GlobalSetup]
  54. public void Setup()
  55. {
  56. // create client, the channel will actually never connect because call logic will be short-circuited
  57. channel = new Channel("localhost", 10042, ChannelCredentials.Insecure);
  58. client = new PingClient(new DefaultCallInvoker(channel));
  59. var native = NativeMethods.Get();
  60. // replace the implementation of a native method with a fake
  61. NativeMethods.Delegates.grpcsharp_call_start_unary_delegate fakeCallStartUnary = (CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags) => {
  62. return native.grpcsharp_test_call_start_unary_echo(call, ctx, sendBuffer, writeFlags, metadataArray, metadataFlags);
  63. };
  64. native.GetType().GetField(nameof(native.grpcsharp_call_start_unary)).SetValue(native, fakeCallStartUnary);
  65. NativeMethods.Delegates.grpcsharp_completion_queue_pluck_delegate fakeCqPluck = (CompletionQueueSafeHandle cq, IntPtr tag) => {
  66. return new CompletionQueueEvent {
  67. type = CompletionQueueEvent.CompletionType.OpComplete,
  68. success = 1,
  69. tag = tag
  70. };
  71. };
  72. native.GetType().GetField(nameof(native.grpcsharp_completion_queue_pluck)).SetValue(native, fakeCqPluck);
  73. }
  74. [GlobalCleanup]
  75. public async Task Cleanup()
  76. {
  77. await channel.ShutdownAsync();
  78. }
  79. class PingClient : ClientBase
  80. {
  81. public PingClient(CallInvoker callInvoker) : base(callInvoker) { }
  82. public byte[] Ping(byte[] request, CallOptions options)
  83. {
  84. return CallInvoker.BlockingUnaryCall(PingMethod, null, options, request);
  85. }
  86. }
  87. }
  88. }