| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- #region Copyright notice and license
- // Copyright 2019 The gRPC Authors
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #endregion
- using System;
- using System.Collections.Generic;
- using BenchmarkDotNet.Attributes;
- using Grpc.Core;
- using Grpc.Core.Internal;
- namespace Grpc.Microbenchmarks
- {
- [ClrJob, CoreJob] // test .NET Core and .NET Framework
- [MemoryDiagnoser] // allocations
- public class Utf8Encode : ISendStatusFromServerCompletionCallback
- {
- [Params(0, 1, 4, 128, 1024)]
- public int PayloadSize
- {
- get { return payloadSize; }
- set
- {
- payloadSize = value;
- status = new Status(StatusCode.OK, Invent(value));
- }
- }
- private int payloadSize;
- private Status status;
- static string Invent(int length)
- {
- var rand = new Random(Seed: length);
- var chars = new char[length];
- for(int i = 0; i < chars.Length; i++)
- {
- chars[i] = (char)rand.Next(32, 300);
- }
- return new string(chars);
- }
- private GrpcEnvironment environment;
- private CompletionRegistry completionRegistry;
- [GlobalSetup]
- public void Setup()
- {
- var native = NativeMethods.Get();
- // nop the native-call via reflection
- NativeMethods.Delegates.grpcsharp_call_send_status_from_server_delegate nop = (CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, IntPtr statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, SliceBufferSafeHandle optionalSendBuffer, WriteFlags writeFlags) => {
- completionRegistry.Extract(ctx.Handle).OnComplete(true); // drain the dictionary as we go
- return CallError.OK;
- };
- native.GetType().GetField(nameof(native.grpcsharp_call_send_status_from_server)).SetValue(native, nop);
- environment = GrpcEnvironment.AddRef();
- metadata = MetadataArraySafeHandle.Create(Metadata.Empty);
- completionRegistry = new CompletionRegistry(environment, () => environment.BatchContextPool.Lease(), () => throw new NotImplementedException());
- var cq = CompletionQueueSafeHandle.CreateAsync(completionRegistry);
- call = CreateFakeCall(cq);
- }
- 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;
- }
- [GlobalCleanup]
- public void Cleanup()
- {
- try
- {
- metadata?.Dispose();
- metadata = null;
- call?.Dispose();
- call = null;
- if (environment != null)
- {
- environment = null;
- // cleanup seems... unreliable on CLR
- // GrpcEnvironment.ReleaseAsync().Wait(1000);
- }
- }
- catch (Exception ex)
- {
- Console.Error.WriteLine(ex.Message);
- }
- }
- private CallSafeHandle call;
- private MetadataArraySafeHandle metadata;
- const int Iterations = 1000;
- [Benchmark(OperationsPerInvoke = Iterations)]
- public unsafe void SendStatus()
- {
- for (int i = 0; i < Iterations; i++)
- {
- call.StartSendStatusFromServer(this, status, metadata, false, SliceBufferSafeHandle.NullInstance, WriteFlags.NoCompress);
- }
- }
- void ISendStatusFromServerCompletionCallback.OnSendStatusFromServerCompletion(bool success) { }
- }
- }
|