I'm trying out MassTransit and compared to "official" library it's very slow when using publisher confirms. I'm getting around 40 msg/s compared to 18.000 msgs/s for official library. I also tried the MassTransit benchmark and using "dotnet run -f netcoreapp3.1 -c Release -- --count=100000 --prefetch=1000 --clients=100" I get 5284 msg/s, but it is not using publisher confirms. I suspect this is because MassTransit is doing synchronous confirmations. Is there a way to speed up MassTransit? I don't think 40 msg/s is going to be enough throughput for us. My code for MassTransit:
namespace MassTransitTest
{
class Program
{
static async Task Main()
{
var busControl = Bus.Factory.CreateUsingRabbitMq();
var source = new CancellationTokenSource(TimeSpan.FromSeconds(10));
await busControl.StartAsync(source.Token);
var sendEndpoint = await busControl.GetSendEndpoint(new Uri("queue:DefaultQueue"));
try
{
Console.WriteLine("Sending value");
for (int i = 0; i < 10000; i++)
{
await sendEndpoint.Send<ValueEntered>(new
{
Value = "Test"
});
}
}
finally
{
await busControl.StopAsync();
}
}
}
}
My code for "official" library:
namespace OfficialLibraryTest
{
class Message
{
public string Text { get; set; }
}
class Program
{
static void Main(string[] args)
{
ConcurrentDictionary<ulong, Message> outstandingConfirms = new ConcurrentDictionary<ulong, Message>();
Serializer serializer = new Serializer(new PropertiesExtractor(), options: GroBufOptions.WriteEmptyObjects);
ConnectionFactory factory = new ConnectionFactory();
factory.AutomaticRecoveryEnabled = true;
factory.HostName = "localhost";
IConnection publishConnection = factory.CreateConnection();
IModel channel = publishConnection.CreateModel();
try
{
channel.ConfirmSelect();
channel.BasicAcks += (sender, ea) =>
{
if (ea.Multiple)
{
var confirmed = outstandingConfirms.Where(k => k.Key <= ea.DeliveryTag);
foreach (var entry in confirmed)
{
outstandingConfirms.TryRemove(entry.Key, out _);
}
}
else
{
outstandingConfirms.TryRemove(ea.DeliveryTag, out _);
}
};
channel.BasicNacks += (sender, ea) =>
{
if (ea.Multiple)
{
var confirmed = outstandingConfirms.Where(k => k.Key <= ea.DeliveryTag);
foreach (var entry in confirmed)
{
outstandingConfirms.TryRemove(entry.Key, out _);
}
}
else
{
outstandingConfirms.TryRemove(ea.DeliveryTag, out _);
}
};
IBasicProperties props = channel.CreateBasicProperties();
props.DeliveryMode = 2;
for (int i = 0; i < 1000000; i++)
{
Message message = new Message { Text = "Test" };
ulong nextSeqNumber = channel.NextPublishSeqNo;
byte[] messageBodyBytes = serializer.Serialize(message);
outstandingConfirms.TryAdd(nextSeqNumber, message);
channel.BasicPublish("DefaultExchange", "DefaultQueue", props, messageBodyBytes);
}
}
finally
{
channel.Dispose();
publishConnection.Dispose();
}
}
}
}