Skip to content

Instantly share code, notes, and snippets.

@mgravell
Last active January 19, 2023 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mgravell/f29a9b00ac5bfd0ca9978747707331ad to your computer and use it in GitHub Desktop.
Save mgravell/f29a9b00ac5bfd0ca9978747707331ad to your computer and use it in GitHub Desktop.
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();
}
BenchmarkDotNet=v0.13.4, OS=Windows 11 (10.0.22621.1105)
Intel Core i9-9900K CPU 3.60GHz (Coffee Lake), 1 CPU, 16 logical and 8 physical cores
.NET SDK=7.0.102
  [Host]   : .NET 7.0.2 (7.0.222.60605), X64 RyuJIT AVX2
  .NET 7.0 : .NET 7.0.2 (7.0.222.60605), X64 RyuJIT AVX2

Job=.NET 7.0  Runtime=.NET 7.0
Method Mean Error StdDev Ratio Gen0 Allocated Alloc Ratio
WithCache 14.53 ns 0.037 ns 0.029 ns 0.31 - - 0.00
WithoutCache 46.35 ns 0.604 ns 0.536 ns 1.00 0.0220 184 B 1.00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment