Files
natsdotnet/tests/NATS.Server.Benchmark.Tests/RequestReply/SingleClientLatencyTests.cs
Joseph Doherty 37575dc41c feat: add benchmark test project for Go vs .NET server comparison
Side-by-side performance benchmarks using NATS.Client.Core against both
servers on ephemeral ports. Includes core pub/sub, request/reply latency,
and JetStream throughput tests with comparison output and
benchmarks_comparison.md results. Also fixes timestamp flakiness in
StoreInterfaceTests by using explicit timestamps.
2026-03-13 01:23:31 -04:00

65 lines
2.2 KiB
C#

using NATS.Client.Core;
using NATS.Server.Benchmark.Tests.Harness;
using NATS.Server.Benchmark.Tests.Infrastructure;
using Xunit.Abstractions;
namespace NATS.Server.Benchmark.Tests.RequestReply;
[Collection("Benchmark-Core")]
public class SingleClientLatencyTests(CoreServerPairFixture fixture, ITestOutputHelper output)
{
private readonly BenchmarkRunner _runner = new() { WarmupCount = 500, MeasurementCount = 10_000 };
[Fact]
[Trait("Category", "Benchmark")]
public async Task RequestReply_SingleClient_128B()
{
const int payloadSize = 128;
const string subject = "bench.reqrep.single";
var dotnetResult = await RunLatency("Request-Reply Single (128B)", "DotNet", subject, payloadSize, fixture.CreateDotNetClient);
if (fixture.GoAvailable)
{
var goResult = await RunLatency("Request-Reply Single (128B)", "Go", subject, payloadSize, fixture.CreateGoClient);
BenchmarkResultWriter.WriteComparison(output, goResult, dotnetResult);
}
else
{
BenchmarkResultWriter.WriteSingle(output, dotnetResult);
}
}
private async Task<BenchmarkResult> RunLatency(string name, string serverType, string subject, int payloadSize, Func<NatsConnection> createClient)
{
var payload = new byte[payloadSize];
await using var serviceClient = createClient();
await using var requestClient = createClient();
await serviceClient.ConnectAsync();
await requestClient.ConnectAsync();
// Start service responder
var sub = await serviceClient.SubscribeCoreAsync<byte[]>(subject);
var responderTask = Task.Run(async () =>
{
await foreach (var msg in sub.Msgs.ReadAllAsync())
{
if (msg.ReplyTo is not null)
await serviceClient.PublishAsync(msg.ReplyTo, payload);
}
});
await Task.Delay(50);
var result = await _runner.MeasureLatencyAsync(name, serverType, payloadSize,
async _ =>
{
await requestClient.RequestAsync<byte[], byte[]>(subject, payload);
});
await sub.UnsubscribeAsync();
return result;
}
}