|
using BenchmarkDotNet.Attributes; |
|
using BenchmarkDotNet.Jobs; |
|
using BenchmarkDotNet.Running; |
|
using Grpc.Core; |
|
using ProtoBuf.Grpc.Client; |
|
using ProtoBuf.Grpc.Configuration; |
|
using System.Collections.Concurrent; |
|
|
|
BenchmarkRunner.Run<MyBenchmark>(); |
|
|
|
[MemoryDiagnoser] |
|
[SimpleJob(RuntimeMoniker.Net70)] |
|
public class MyBenchmark |
|
{ |
|
private readonly ChannelBase _grpcChannel = new DummyChannel(); |
|
|
|
private readonly ConcurrentDictionary<Type, object> _channelCache = new(); |
|
|
|
[Benchmark] |
|
public IService WithCache() => GetGrpcServiceWithCache<IService>(); |
|
[Benchmark(Baseline = true)] |
|
public IService WithoutCache() => _grpcChannel.CreateGrpcService<IService>(); |
|
private T GetGrpcServiceWithCache<T>() where T : class |
|
{ |
|
if (_channelCache.TryGetValue(typeof(T), out var obj)) |
|
return (T)obj; |
|
|
|
var service = _grpcChannel.CreateGrpcService<T>(); |
|
|
|
if (!_channelCache.TryAdd(typeof(T), service)) |
|
service = (T)_channelCache[typeof(T)]; |
|
|
|
return service; |
|
} |
|
|
|
|
|
|
|
} |
|
[Service] |
|
public interface IService { } |
|
|
|
sealed class DummyChannel : ChannelBase |
|
{ |
|
public DummyChannel() : base("") { } |
|
public override CallInvoker CreateCallInvoker() |
|
=> DummyCallInvoker.Instance; |
|
} |
|
sealed class DummyCallInvoker : CallInvoker |
|
{ |
|
public static DummyCallInvoker Instance { get; } = new(); |
|
|
|
public override AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string? host, CallOptions options) => throw new NotSupportedException(); |
|
|
|
public override AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string? host, CallOptions options) => throw new NotSupportedException(); |
|
|
|
public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string? host, CallOptions options, TRequest request) => throw new NotSupportedException(); |
|
|
|
public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string? host, CallOptions options, TRequest request) => throw new NotSupportedException(); |
|
|
|
public override TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string? host, CallOptions options, TRequest request) => throw new NotSupportedException(); |
|
} |