diff --git a/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/RedisProtocolBenchmark.cs b/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/RedisProtocolBenchmark.cs new file mode 100644 index 0000000000..c856613edb --- /dev/null +++ b/benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/RedisProtocolBenchmark.cs @@ -0,0 +1,148 @@ +using System; +using System.Buffers; +using System.Collections.Generic; +using BenchmarkDotNet.Attributes; +using Microsoft.AspNetCore.Connections; +using Microsoft.AspNetCore.SignalR.Internal; +using Microsoft.AspNetCore.SignalR.Internal.Protocol; +using Microsoft.AspNetCore.SignalR.Redis.Internal; + +namespace Microsoft.AspNetCore.SignalR.Microbenchmarks +{ + public class RedisProtocolBenchmark + { + private RedisProtocol _protocol; + private RedisGroupCommand _groupCommand; + private object[] _args; + private string _methodName; + private IReadOnlyList _excludedIdsSmall; + private IReadOnlyList _excludedIdsLarge; + private byte[] _writtenAck; + private byte[] _writtenGroupCommand; + private byte[] _writtenInvocationNoExclusions; + private byte[] _writtenInvocationSmallExclusions; + private byte[] _writtenInvocationLargeExclusions; + + [GlobalSetup] + public void GlobalSetup() + { + _protocol = new RedisProtocol(new [] { + new DummyProtocol("protocol1"), + new DummyProtocol("protocol2") + }); + + _groupCommand = new RedisGroupCommand(id: 42, serverName: "Server", GroupAction.Add, groupName: "group", connectionId: "connection"); + + // Because of the DummyProtocol, the args don't really matter + _args = Array.Empty(); + _methodName = "Method"; + + _excludedIdsSmall = GenerateIds(2); + _excludedIdsLarge = GenerateIds(20); + + _writtenAck = _protocol.WriteAck(42); + _writtenGroupCommand = _protocol.WriteGroupCommand(_groupCommand); + _writtenInvocationNoExclusions = _protocol.WriteInvocation(_methodName, _args, null); + _writtenInvocationSmallExclusions = _protocol.WriteInvocation(_methodName, _args, _excludedIdsSmall); + _writtenInvocationLargeExclusions = _protocol.WriteInvocation(_methodName, _args, _excludedIdsLarge); + } + + [Benchmark] + public void WriteAck() + { + _protocol.WriteAck(42); + } + + [Benchmark] + public void WriteGroupCommand() + { + _protocol.WriteGroupCommand(_groupCommand); + } + + [Benchmark] + public void WriteInvocationNoExclusions() + { + _protocol.WriteInvocation(_methodName, _args); + } + + [Benchmark] + public void WriteInvocationSmallExclusions() + { + _protocol.WriteInvocation(_methodName, _args, _excludedIdsSmall); + } + + [Benchmark] + public void WriteInvocationLargeExclusions() + { + _protocol.WriteInvocation(_methodName, _args, _excludedIdsLarge); + } + + [Benchmark] + public void ReadAck() + { + _protocol.ReadAck(_writtenAck); + } + + [Benchmark] + public void ReadGroupCommand() + { + _protocol.ReadGroupCommand(_writtenGroupCommand); + } + + [Benchmark] + public void ReadInvocationNoExclusions() + { + _protocol.ReadInvocation(_writtenInvocationNoExclusions); + } + + [Benchmark] + public void ReadInvocationSmallExclusions() + { + _protocol.ReadInvocation(_writtenInvocationSmallExclusions); + } + + [Benchmark] + public void ReadInvocationLargeExclusions() + { + _protocol.ReadInvocation(_writtenInvocationLargeExclusions); + } + + private static IReadOnlyList GenerateIds(int count) + { + var ids = new string[count]; + for(var i = 0; i < count; i++) + { + ids[i] = Guid.NewGuid().ToString("N"); + } + return ids; + } + + private class DummyProtocol: IHubProtocol + { + private static byte[] _fixedOutput = new byte[] { 0x68, 0x68, 0x6C, 0x6C, 0x6F }; + + public string Name { get; } + + public int Version => 1; + + public TransferFormat TransferFormat => TransferFormat.Text; + + public DummyProtocol(string name) + { + Name = name; + } + + public bool IsVersionSupported(int version) => true; + + public bool TryParseMessage(ref ReadOnlySequence input, IInvocationBinder binder, out HubMessage message) + { + throw new NotSupportedException(); + } + + public void WriteMessage(HubMessage message, IBufferWriter output) + { + output.Write(_fixedOutput); + } + } + } +}