static async Task Main(string[] args) { Log.Logger = new LoggerConfiguration() .WriteTo.Console() .MinimumLevel.Warning() .WriteTo.Seq("http://localhost:5341") .Enrich.WithProperty("AppName", "JustSaying.Benchmark") .CreateLogger(); try { await Parser.Default.ParseArguments <JustSayingBenchmark>(args) .MapResult(async a => await JustSayingBenchmark.RunTest(a), errs => Task.CompletedTask); } finally { Log.CloseAndFlush(); } }
public static async Task RunTest(JustSayingBenchmark options) { Console.WriteLine("Running benchmark with message count of {0}", options.MessageCount); var capture = new MessageMetricCapture(options.MessageCount); var services = new ServiceCollection() .AddSingleton <IReportConsumerMetric>(capture) .AddLogging(lg => lg.AddSerilog()); RegisterJustSaying(services); var provider = services.BuildServiceProvider(); var publisher = provider.GetService <IMessagePublisher>(); using (Operation.Time("Executing startup work")) { await publisher.StartAsync(CancellationToken.None); var bus = provider.GetService <IMessagingBus>(); await bus.StartAsync(CancellationToken.None); } Console.WriteLine("Completed startup, beginning benchmark"); var watch = new Stopwatch(); var taskBatches = Enumerable.Range(0, options.MessageCount).Batch(20) .Select(async batch => { var messageTasks = batch.Select(id => new BenchmarkMessage(watch.Elapsed, id)) .Select(async x => await capture.Sent(x.Id, publisher.PublishAsync(x))); await Task.WhenAll(messageTasks); }).ToList(); var batchId = 1; var batchCount = taskBatches.Count; foreach (var taskBatch in taskBatches) { using (Operation.Time("Sending batch id {BatchId} of {BatchCount}", batchId, batchCount)) { await taskBatch; } } Log.Information("Waiting for sends to complete..."); await capture.SendCompleted; Log.Information("Waiting for consumes to complete..."); await capture.ConsumeCompleted; Log.Information("Sends and Consumes completed!"); var messageMetrics = capture.GetMessageMetrics(); Console.WriteLine("Avg Ack Time: {0:F0}ms", messageMetrics.Average(x => x.AckLatency) * 1000 / Stopwatch.Frequency); Console.WriteLine("Min Ack Time: {0:F0}ms", messageMetrics.Min(x => x.AckLatency) * 1000 / Stopwatch.Frequency); Console.WriteLine("Max Ack Time: {0:F0}ms", messageMetrics.Max(x => x.AckLatency) * 1000 / Stopwatch.Frequency); Console.WriteLine("Med Ack Time: {0:F0}ms", messageMetrics.Median(x => x.AckLatency) * 1000 / Stopwatch.Frequency); Console.WriteLine("95t Ack Time: {0:F0}ms", messageMetrics.Percentile(x => x.AckLatency) * 1000 / Stopwatch.Frequency); Console.WriteLine("Avg Consume Time: {0:F0}ms", messageMetrics.Average(x => x.ConsumeLatency) * 1000 / Stopwatch.Frequency); Console.WriteLine("Min Consume Time: {0:F0}ms", messageMetrics.Min(x => x.ConsumeLatency) * 1000 / Stopwatch.Frequency); Console.WriteLine("Max Consume Time: {0:F0}ms", messageMetrics.Max(x => x.ConsumeLatency) * 1000 / Stopwatch.Frequency); Console.WriteLine("Med Consume Time: {0:F0}ms", messageMetrics.Median(x => x.ConsumeLatency) * 1000 / Stopwatch.Frequency); Console.WriteLine("95t Consume Time: {0:F0}ms", messageMetrics.Percentile(x => x.ConsumeLatency) * 1000 / Stopwatch.Frequency); DrawResponseTimeGraph(messageMetrics, m => m.ConsumeLatency); }