Example #1
0
        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);
        }