File: BroadcastBenchmark.cs
Web Access
Project: src\src\SignalR\perf\Microbenchmarks\Microsoft.AspNetCore.SignalR.Microbenchmarks.csproj (Microsoft.AspNetCore.SignalR.Microbenchmarks)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.IO.Pipelines;
using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.SignalR.Internal;
using Microsoft.AspNetCore.SignalR.Protocol;
using Microsoft.Extensions.Logging.Abstractions;
 
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks;
 
public class BroadcastBenchmark
{
    private const string TestGroupName = "TestGroup";
    private DefaultHubLifetimeManager<Hub> _hubLifetimeManager;
    private HubContext<Hub> _hubContext;
 
    [Params(1, 10, 1000)]
    public int Connections;
 
    [Params("json", "msgpack")]
    public string Protocol;
 
    [GlobalSetup]
    public void GlobalSetup()
    {
        _hubLifetimeManager = new DefaultHubLifetimeManager<Hub>(NullLogger<DefaultHubLifetimeManager<Hub>>.Instance);
 
        IHubProtocol protocol;
 
        if (Protocol == "json")
        {
            protocol = new NewtonsoftJsonHubProtocol();
        }
        else
        {
            protocol = new MessagePackHubProtocol();
        }
 
        var options = new PipeOptions();
        for (var i = 0; i < Connections; ++i)
        {
            var pair = DuplexPipe.CreateConnectionPair(options, options);
            var connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Application, pair.Transport);
            var contextOptions = new HubConnectionContextOptions()
            {
                KeepAliveInterval = Timeout.InfiniteTimeSpan,
            };
            var hubConnection = new HubConnectionContext(connection, contextOptions, NullLoggerFactory.Instance);
            hubConnection.Protocol = protocol;
            _hubLifetimeManager.OnConnectedAsync(hubConnection).GetAwaiter().GetResult();
            _hubLifetimeManager.AddToGroupAsync(connection.ConnectionId, TestGroupName).GetAwaiter().GetResult();
 
            _ = ConsumeAsync(connection.Application);
        }
 
        _hubContext = new HubContext<Hub>(_hubLifetimeManager);
    }
 
    [Benchmark]
    public Task SendAsyncGroup()
    {
        return _hubContext.Clients.Group(TestGroupName).SendAsync("Method");
    }
 
    [Benchmark]
    public Task SendAsyncAll()
    {
        return _hubContext.Clients.All.SendAsync("Method");
    }
 
    // Consume the data written to the transport
    private static async Task ConsumeAsync(IDuplexPipe application)
    {
        while (true)
        {
            var result = await application.Input.ReadAsync();
            var buffer = result.Buffer;
 
            if (!buffer.IsEmpty)
            {
                application.Input.AdvanceTo(buffer.End);
            }
            else if (result.IsCompleted)
            {
                break;
            }
        }
 
        application.Input.Complete();
    }
}