예제 #1
0
        public static async Task MeasureFirstRequest(string[] args)
        {
            var url = args.FirstOrDefault(arg => arg.StartsWith("http", StringComparison.OrdinalIgnoreCase));

            if (url == null)
            {
                Console.WriteLine("URL not found, skipping first request");
                return;
            }

            var cts         = new CancellationTokenSource(30000);
            var httpMessage = new HttpRequestMessage(HttpMethod.Get, url);

            var stopwatch = new Stopwatch();

            stopwatch.Start();

            try
            {
                using (var response = await _httpClient.SendAsync(httpMessage, cts.Token))
                {
                    var elapsed = stopwatch.ElapsedMilliseconds;
                    Console.WriteLine($"{elapsed} ms");

                    BenchmarksEventSource.Register("http/firstrequest", Operations.Max, Operations.Max, "First Request (ms)", "Time to first request in ms", "n0");
                    BenchmarksEventSource.Measure("http/firstrequest", elapsed);
                }
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("A timeout occurred while measuring the first request");
            }
        }
예제 #2
0
        static void Main(string[] args)
        {
#if RUNNING_CRANK
            Console.WriteLine("Application started.");
            Stopwatch sw = new();
            sw.Start();
#endif
            SerializationMechanism.RunBenchmark();
#if RUNNING_CRANK
            sw.Stop();

            Process process = Process.GetCurrentProcess();
            process.Refresh();

            //Console.WriteLine(process.PrivateMemorySize64 / 1024);
            //Console.WriteLine(sw.ElapsedMilliseconds);

            BenchmarksEventSource.Register("runtime/private-bytes", Operations.First, Operations.First, "Private bytes (KB)", "Private bytes (KB)", "n0");
            BenchmarksEventSource.Measure("runtime/private-bytes", process.PrivateMemorySize64 / 1024);

            BenchmarksEventSource.Register("application/elapsed-time", Operations.First, Operations.First, "Elapsed time (ms)", "Elasped time (ms)", "n0");
            BenchmarksEventSource.Measure("application/elapsed-time", sw.ElapsedMilliseconds);

            //Thread.Sleep(2000);
#endif
        }
예제 #3
0
        public async Task Run(ClientParameters clientParams, LoadGeneratorParameters loadParams)
        {
            var secrets     = SecretConfiguration.Load(clientParams.SecretSource);
            var hostBuilder = new HostBuilder().UseOrleansClient((ctx, builder) =>
                                                                 builder.Configure <ClusterOptions>(options => { options.ClusterId = clientParams.ClusterId; options.ServiceId = clientParams.ServiceId; })
                                                                 .Configure <ConnectionOptions>(options => clientParams.ConnectionsPerEndpoint = 2)
                                                                 .UseAzureStorageClustering(options => options.ConfigureTableServiceClient(secrets.ClusteringConnectionString)));

            using var host = hostBuilder.Build();

            _logger.LogInformation("Connecting to cluster...");
            await host.StartAsync();

            var client = host.Services.GetService <IClusterClient>();

            var generator = new ConcurrentLoadGenerator <T>(
                numWorkers: loadParams.NumWorkers,
                blocksPerWorker: loadParams.BlocksPerWorker != 0 ? loadParams.BlocksPerWorker : int.MaxValue,
                requestsPerBlock: loadParams.RequestsPerBlock,
                issueRequest: _scenario.IssueRequest,
                getStateForWorker: workerId => _scenario.GetStateForWorker(client, workerId),
                logger: _logger,
                logIntermediateResults: true);

            _logger.LogInformation("Warming-up...");
            await generator.Warmup();

            var cts = loadParams.Duration != 0
                ? new CancellationTokenSource(TimeSpan.FromSeconds(loadParams.Duration))
                : new CancellationTokenSource();

            _logger.LogInformation("Running");
            var report = await generator.Run(cts.Token);

            // Register the measurements. n0 -> format as natural number
            BenchmarksEventSource.Register("requests", Operations.First, Operations.Sum, "Requests", "Number of requests completed", "n0");
            BenchmarksEventSource.Register("failures", Operations.First, Operations.Sum, "Failures", "Number of failures", "n0");
            BenchmarksEventSource.Register("rps", Operations.First, Operations.Sum, "Rate per second", "Rate per seconds", "n0");

            // Register the measurement values
            BenchmarksEventSource.Measure("requests", report.Completed);
            BenchmarksEventSource.Measure("failures", report.Failures);
            BenchmarksEventSource.Measure("rps", report.RatePerSecond);

            await host.StopAsync();
        }
예제 #4
0
        private async Task RunAsync(Parameters parameters)
        {
            _logger.LogInformation("Connecting to cluster...");
            var secrets     = SecretConfiguration.Load(parameters.SecretSource);
            var hostBuilder = new HostBuilder()
                              .UseOrleansClient(builder => {
                builder
                .Configure <ClusterOptions>(options => { options.ClusterId = parameters.ClusterId; options.ServiceId = parameters.ServiceId; })
                .UseAzureStorageClustering(options => options.ConfigureTableServiceClient(secrets.ClusteringConnectionString));
            });

            using var host = hostBuilder.Build();
            await host.StartAsync();

            var client = host.Services.GetService <IClusterClient>();

            var counterGrain = client.GetGrain <ICounterGrain>(parameters.CounterKey);

            var duration = await counterGrain.GetRunDuration();

            BenchmarksEventSource.Register("duration", Operations.First, Operations.Last, "duration", "duration", "n0");
            BenchmarksEventSource.Measure("duration", duration.TotalSeconds);

            var initialWait = await counterGrain.WaitTimeForReport();

            _logger.LogInformation($"Counters should be ready in {initialWait}");
            await Task.Delay(initialWait);

            _logger.LogInformation($"Counters ready");
            foreach (var counter in parameters.Counters)
            {
                var value = await counterGrain.GetTotalCounterValue(counter);

                _logger.LogInformation($"{counter}: {value}");
                BenchmarksEventSource.Register(counter, Operations.First, Operations.Sum, counter, counter, "n0");
                BenchmarksEventSource.Measure(counter, value);
                if (string.Equals(counter, "requests", StringComparison.InvariantCultureIgnoreCase))
                {
                    var rps = (float)value / duration.TotalSeconds;
                    BenchmarksEventSource.Register("rps", Operations.First, Operations.Last, "rps", "Requests per second", "n0");
                    BenchmarksEventSource.Measure("rps", rps);
                }
            }

            await host.StopAsync();
        }
예제 #5
0
        private static void ParseOutput()
        {
            BenchmarksEventSource.Register("h2load/requests;http/requests", Operations.Max, Operations.Sum, "Requests", "Total number of requests", "n0");
            BenchmarksEventSource.Register("h2load/badresponses;http/requests/badresponses", Operations.Max, Operations.Sum, "Bad responses", "Non-2xx or 3xx responses", "n0");
            BenchmarksEventSource.Register("h2load/errors/socketerrors;http/requests/errors", Operations.Max, Operations.Sum, "Socket errors", "Socket errors", "n0");

            BenchmarksEventSource.Register("h2load/latency/mean;http/latency/mean", Operations.Max, Operations.Sum, "Mean latency (ms)", "Mean latency (ms)", "n2");
            BenchmarksEventSource.Register("h2load/latency/max;http/latency/max", Operations.Max, Operations.Sum, "Max latency (ms)", "Max latency (ms)", "n2");

            BenchmarksEventSource.Register("h2load/rps/max;http/rps/max", Operations.Max, Operations.Sum, "Max RPS", "RPS: max", "n0");
            BenchmarksEventSource.Register("h2load/raw", Operations.All, Operations.All, "Raw results", "Raw results", "object");

            double rps      = 0;
            var    rpsMatch = Regex.Match(Output, @"([\d\.]+) req/s");

            if (rpsMatch.Success && rpsMatch.Groups.Count == 2)
            {
                rps = double.Parse(rpsMatch.Groups[1].Value);
            }

            var latencyMatch   = Regex.Match(Output, @"time for request: \s+[\d\.]+\w+\s+[\d\.]+\w+\s+([\d\.]+)(\w+)");
            var averageLatency = ReadLatency(latencyMatch);

            var p100Match  = Regex.Match(Output, @"time for request: \s+[\d\.]+\w+\s+([\d\.]+)(\w+)");
            var maxLatency = ReadLatency(p100Match);

            var socketErrorsMatch = Regex.Match(Output, @"([\d\.]+) failed, ([\d\.]+) errored, ([\d\.]+) timeout");
            var socketErrors      = CountSocketErrors(socketErrorsMatch);

            var badResponsesMatch = Regex.Match(Output, @"status codes: ([\d\.]+) 2xx, ([\d\.]+) 3xx, ([\d\.]+) 4xx, ([\d\.]+) 5xx");
            var badResponses      = ReadBadResponses(badResponsesMatch);

            var requestsCountMatch = Regex.Match(Output, @"requests: ([\d\.]+) total");
            var totalRequests      = ReadRequests(requestsCountMatch);

            BenchmarksEventSource.Measure("h2load/requests;http/requests", totalRequests);
            BenchmarksEventSource.Measure("h2load/badresponses;http/requests/badresponses", badResponses);
            BenchmarksEventSource.Measure("h2load/errors/socketerrors;http/requests/errors", socketErrors);

            BenchmarksEventSource.Measure("h2load/latency/mean;http/latency/mean", averageLatency);
            BenchmarksEventSource.Measure("h2load/latency/max;http/latency/max", maxLatency);

            BenchmarksEventSource.Measure("h2load/rps/max;http/rps/max", rps);

            BenchmarksEventSource.Measure("h2load/raw", Output);
        }
예제 #6
0
        public static async Task MeasureFirstRequest(string[] args)
        {
            var url = args.FirstOrDefault(arg => arg.StartsWith("http", StringComparison.OrdinalIgnoreCase));

            if (url == null)
            {
                Console.WriteLine("URL not found, skipping first request");
                return;
            }

            // Configuring the http client to trust the self-signed certificate
            var httpClientHandler = new HttpClientHandler();

            httpClientHandler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
            httpClientHandler.MaxConnectionsPerServer = 1;

            using (var httpClient = new HttpClient(httpClientHandler))
            {
                var cts         = new CancellationTokenSource(5000);
                var httpMessage = new HttpRequestMessage(HttpMethod.Get, url);

                var stopwatch = new Stopwatch();
                stopwatch.Start();

                try
                {
                    using (var response = await httpClient.SendAsync(httpMessage, cts.Token))
                    {
                        var elapsed = stopwatch.ElapsedMilliseconds;
                        Console.WriteLine($"{elapsed} ms");

                        BenchmarksEventSource.Register("http/firstrequest", Operations.Max, Operations.Max, "First Request (ms)", "Time to first request in ms", "n0");
                        BenchmarksEventSource.Measure("http/firstrequest", elapsed);
                    }
                }
                catch (OperationCanceledException)
                {
                    Console.WriteLine("A timeout occurred while measuring the first request");
                }
            }
        }
예제 #7
0
        static async Task <int> Main(string[] args)
        {
            Console.WriteLine("Bombardier Client");
            Console.WriteLine("args: " + String.Join(' ', args));

            Console.Write("Measuring first request ... ");
            await MeasureFirstRequest(args);

            // Extracting parameters
            var argsList = args.ToList();

            TryGetArgumentValue("-w", argsList, out int warmup);
            TryGetArgumentValue("-d", argsList, out int duration);
            TryGetArgumentValue("-n", argsList, out int requests);
            TryGetArgumentValue("-o", argsList, out string outputFormat);
            TryGetArgumentValue("-f", argsList, out string bodyFile);

            if (duration == 0 && requests == 0)
            {
                Console.WriteLine("Couldn't find valid -d and -n arguments (integers)");
                return(-1);
            }

            if (string.IsNullOrEmpty(outputFormat))
            {
                outputFormat = "json";
            }
            else if ((outputFormat != "json") && (outputFormat != "plain-text"))
            {
                Console.WriteLine("Value value for -o is json or plain-text");
                return(-1);
            }

            args = argsList.ToArray();

            string bombardierUrl     = null;
            string bombardierVersion = "1.2.5";

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                bombardierUrl = "https://github.com/codesenberg/bombardier/releases/download/v1.2.5/bombardier-windows-amd64.exe";
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                switch (RuntimeInformation.ProcessArchitecture)
                {
                case Architecture.Arm64: bombardierUrl = "https://github.com/codesenberg/bombardier/releases/download/v1.2.5/bombardier-linux-arm64"; break;

                case Architecture.Arm: bombardierUrl = "https://github.com/codesenberg/bombardier/releases/download/v1.2.5/bombardier-linux-arm"; break;

                default: bombardierUrl = "https://github.com/codesenberg/bombardier/releases/download/v1.2.5/bombardier-linux-amd64"; break;
                }
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                bombardierUrl = "https://github.com/codesenberg/bombardier/releases/download/v1.2.5/bombardier-darwin-amd64";
            }
            else
            {
                Console.WriteLine("Unsupported platform");
                return(-1);
            }

            var bombardierFileName = Path.Combine(Path.GetTempPath(), ".crank", bombardierVersion, Path.GetFileName(bombardierUrl));

            if (!File.Exists(bombardierFileName))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(bombardierFileName));

                Console.WriteLine($"Downloading bombardier from {bombardierUrl} to {bombardierFileName}");

                using (var downloadStream = await _httpClient.GetStreamAsync(bombardierUrl))
                    using (var fileStream = File.Create(bombardierFileName))
                    {
                        await downloadStream.CopyToAsync(fileStream);

                        await fileStream.FlushAsync();

                        await downloadStream.FlushAsync();
                    }
            }

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ||
                RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                Console.WriteLine($"Setting execute permission on executable {bombardierFileName}");
                Process.Start("chmod", "+x " + bombardierFileName);
            }

            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                Console.WriteLine($"Allow running bombardier");
                Process.Start("spctl", "--add " + bombardierFileName);
            }

            if (!String.IsNullOrEmpty(bodyFile))
            {
                if (bodyFile.StartsWith("http", StringComparison.OrdinalIgnoreCase))
                {
                    Console.WriteLine($"Downloading body file {bodyFile}");
                    var tempFile = Path.GetTempFileName();

                    using (var downloadStream = await _httpClient.GetStreamAsync(bodyFile))
                        using (var fileStream = File.Create(tempFile))
                        {
                            await downloadStream.CopyToAsync(fileStream);
                        }

                    bodyFile = tempFile;
                }

                argsList.Add("-f");
                argsList.Add(bodyFile);
            }

            args = argsList.Select(Quote).ToArray();

            var baseArguments = String.Join(' ', args) + $" --print r --format {outputFormat}";

            var process = new Process()
            {
                StartInfo =
                {
                    FileName               = bombardierFileName,
                    RedirectStandardOutput = true,
                    UseShellExecute        = false,
                },
                EnableRaisingEvents = true
            };

            var stringBuilder = new StringBuilder();

            process.OutputDataReceived += (_, e) =>
            {
                if (e != null && e.Data != null)
                {
                    Console.WriteLine(e.Data);

                    lock (stringBuilder)
                    {
                        stringBuilder.AppendLine(e.Data);
                    }
                }
            };

            // Warmup

            if (warmup > 0)
            {
                process.StartInfo.Arguments = $" -d {warmup}s {baseArguments}";

                Console.WriteLine("> bombardier " + process.StartInfo.Arguments);

                await StartProcessWithRetriesAsync(process);

                process.WaitForExit();

                if (process.ExitCode != 0)
                {
                    Console.WriteLine("Failed to run bombardier.");
                    return(process.ExitCode);
                }
            }
            else
            {
                Console.WriteLine("Warmup skipped");
            }

            lock (stringBuilder)
            {
                stringBuilder.Clear();
            }

            if (duration > 0)
            {
                process.StartInfo.Arguments =
                    requests > 0
                        ? $" -n {requests} {baseArguments}"
                        : $" -d {duration}s {baseArguments}";

                Console.WriteLine("> bombardier " + process.StartInfo.Arguments);

                await StartProcessWithRetriesAsync(process);

                BenchmarksEventSource.SetChildProcessId(process.Id);

                process.BeginOutputReadLine();
                process.WaitForExit();

                if (process.ExitCode != 0)
                {
                    return(process.ExitCode);
                }

                string output;

                lock (stringBuilder)
                {
                    output = stringBuilder.ToString();
                }

                if (outputFormat != "json")
                {
                    return(0);
                }

                var document = JObject.Parse(output);

                BenchmarksEventSource.Register("bombardier/requests;http/requests", Operations.Max, Operations.Sum, "Requests", "Total number of requests", "n0");
                BenchmarksEventSource.Register("bombardier/badresponses;http/requests/badresponses", Operations.Max, Operations.Sum, "Bad responses", "Non-2xx or 3xx responses", "n0");

                BenchmarksEventSource.Register("bombardier/latency/50;http/latency/50", Operations.Max, Operations.Max, "Latency 50th (ms)", "Latency 50th (ms)", "n2");
                BenchmarksEventSource.Register("bombardier/latency/75;http/latency/75", Operations.Max, Operations.Max, "Latency 75th (ms)", "Latency 75th (ms)", "n2");
                BenchmarksEventSource.Register("bombardier/latency/90;http/latency/90", Operations.Max, Operations.Max, "Latency 90th (ms)", "Latency 90th (ms)", "n2");
                BenchmarksEventSource.Register("bombardier/latency/95;http/latency/95", Operations.Max, Operations.Max, "Latency 95th (ms)", "Latency 95th (ms)", "n2");
                BenchmarksEventSource.Register("bombardier/latency/99;http/latency/99", Operations.Max, Operations.Max, "Latency 99th (ms)", "Latency 99th (ms)", "n2");

                BenchmarksEventSource.Register("bombardier/latency/mean;http/latency/mean", Operations.Max, Operations.Avg, "Mean latency (ms)", "Mean latency (ms)", "n2");
                BenchmarksEventSource.Register("bombardier/latency/max;http/latency/max", Operations.Max, Operations.Max, "Max latency (ms)", "Max latency (ms)", "n2");

                BenchmarksEventSource.Register("bombardier/rps/mean;http/rps/mean", Operations.Max, Operations.Sum, "Requests/sec", "Requests per second", "n0");
                BenchmarksEventSource.Register("bombardier/rps/max;http/rps/max", Operations.Max, Operations.Sum, "Requests/sec (max)", "Max requests per second", "n0");
                BenchmarksEventSource.Register("bombardier/throughput;http/throughput", Operations.Max, Operations.Sum, "Read throughput (MB/s)", "Read throughput (MB/s)", "n2");

                BenchmarksEventSource.Register("bombardier/raw", Operations.All, Operations.All, "Raw results", "Raw results", "json");

                var total =
                    document["result"]["req1xx"].Value <long>()
                    + document["result"]["req2xx"].Value <long>()
                    + document["result"]["req3xx"].Value <long>()
                    + document["result"]["req4xx"].Value <long>()
                    + document["result"]["req5xx"].Value <long>()
                    + document["result"]["others"].Value <long>();

                var success = document["result"]["req2xx"].Value <long>() + document["result"]["req3xx"].Value <long>();

                BenchmarksEventSource.Measure("bombardier/requests;http/requests", total);
                BenchmarksEventSource.Measure("bombardier/badresponses;http/requests/badresponses", total - success);

                BenchmarksEventSource.Measure("bombardier/latency/50;http/latency/50", document["result"]["latency"]["percentiles"]["50"].Value <double>().ToMilliseconds());
                BenchmarksEventSource.Measure("bombardier/latency/75;http/latency/75", document["result"]["latency"]["percentiles"]["75"].Value <double>().ToMilliseconds());
                BenchmarksEventSource.Measure("bombardier/latency/90;http/latency/90", document["result"]["latency"]["percentiles"]["90"].Value <double>().ToMilliseconds());
                BenchmarksEventSource.Measure("bombardier/latency/95;http/latency/95", document["result"]["latency"]["percentiles"]["95"].Value <double>().ToMilliseconds());
                BenchmarksEventSource.Measure("bombardier/latency/99;http/latency/99", document["result"]["latency"]["percentiles"]["99"].Value <double>().ToMilliseconds());

                BenchmarksEventSource.Measure("bombardier/latency/mean;http/latency/mean", document["result"]["latency"]["mean"].Value <double>().ToMilliseconds());
                BenchmarksEventSource.Measure("bombardier/latency/max;http/latency/max", document["result"]["latency"]["max"].Value <double>().ToMilliseconds());

                BenchmarksEventSource.Measure("bombardier/rps/max;http/rps/max", document["result"]["rps"]["max"].Value <double>());
                BenchmarksEventSource.Measure("bombardier/rps/mean;http/rps/mean", document["result"]["rps"]["mean"].Value <double>());

                BenchmarksEventSource.Measure("bombardier/raw", output);

                var bytesPerSecond = document["result"]["bytesRead"].Value <long>() / document["result"]["timeTakenSeconds"].Value <double>();

                // B/s to MB/s
                BenchmarksEventSource.Measure("bombardier/throughput;http/throughput", bytesPerSecond / 1024 / 1024);
            }
            else
            {
                Console.WriteLine("Benchmark skipped");
            }

            // Clean temporary files
            try
            {
                File.Delete(bodyFile);
            }
            catch
            {
            }

            return(0);
        }
예제 #8
0
        static int RunCore(string fileName, string[] args, bool parseLatency)
        {
            // Extracting duration parameters
            string warmup   = "";
            string duration = "";

            var argsList = args.ToList();

            var durationIndex = argsList.FindIndex(x => String.Equals(x, "-d", StringComparison.OrdinalIgnoreCase));

            if (durationIndex >= 0)
            {
                duration = argsList[durationIndex + 1];
                argsList.RemoveAt(durationIndex);
                argsList.RemoveAt(durationIndex);
            }
            else
            {
                Console.WriteLine("Couldn't find -d argument");
                return(-1);
            }

            var warmupIndex = argsList.FindIndex(x => String.Equals(x, "-w", StringComparison.OrdinalIgnoreCase));

            if (warmupIndex >= 0)
            {
                warmup = argsList[warmupIndex + 1];
                argsList.RemoveAt(warmupIndex);
                argsList.RemoveAt(warmupIndex);
            }

            args = argsList.Select(Quote).ToArray();

            var baseArguments = String.Join(' ', args);

            var process = new Process()
            {
                StartInfo =
                {
                    FileName               = fileName,
                    RedirectStandardOutput = true,
                    UseShellExecute        = false,
                },
                EnableRaisingEvents = true
            };

            var stringBuilder = new StringBuilder();

            process.OutputDataReceived += (_, e) =>
            {
                if (e != null && e.Data != null)
                {
                    Console.WriteLine(e.Data);

                    lock (stringBuilder)
                    {
                        stringBuilder.AppendLine(e.Data);
                    }
                }
            };

            // Warmup

            if (!String.IsNullOrEmpty(warmup) && warmup != "0s")
            {
                process.StartInfo.Arguments = $"-d {warmup} {baseArguments}";

                Console.WriteLine("> wrk " + process.StartInfo.Arguments);

                process.Start();
                process.WaitForExit();

                if (process.ExitCode != 0)
                {
                    return(process.ExitCode);
                }
            }

            lock (stringBuilder)
            {
                stringBuilder.Clear();
            }

            process.StartInfo.Arguments = $"-d {duration} {baseArguments}";

            Console.WriteLine("> wrk " + process.StartInfo.Arguments);

            process.Start();

            BenchmarksEventSource.SetChildProcessId(process.Id);

            process.BeginOutputReadLine();
            process.WaitForExit();

            if (process.ExitCode != 0)
            {
                return(process.ExitCode);
            }

            string output;

            lock (stringBuilder)
            {
                output = stringBuilder.ToString();
            }

            BenchmarksEventSource.Register("wrk/rps/mean", Operations.Max, Operations.Sum, "Requests/sec", "Requests per second", "n0");
            BenchmarksEventSource.Register("wrk/requests", Operations.Max, Operations.Sum, "Requests", "Total number of requests", "n0");
            BenchmarksEventSource.Register("wrk/latency/mean", Operations.Max, Operations.Sum, "Mean latency (ms)", "Mean latency (ms)", "n2");
            BenchmarksEventSource.Register("wrk/latency/max", Operations.Max, Operations.Sum, "Max latency (ms)", "Max latency (ms)", "n2");
            BenchmarksEventSource.Register("wrk/errors/badresponses", Operations.Max, Operations.Sum, "Bad responses", "Non-2xx or 3xx responses", "n0");
            BenchmarksEventSource.Register("wrk/errors/socketerrors", Operations.Max, Operations.Sum, "Socket errors", "Socket errors", "n0");
            BenchmarksEventSource.Register("wrk/throughput", Operations.Max, Operations.Sum, "Read throughput (MB/s)", "Read throughput (MB/s)", "n2");

            const string LatencyPattern = @"\s+{0}\s+([\d\.]+)(\w+)";

            var latencyMatch = Regex.Match(output, String.Format(LatencyPattern, "Latency"));

            BenchmarksEventSource.Measure("wrk/latency/mean", ReadLatency(latencyMatch));

            var rpsMatch = Regex.Match(output, @"Requests/sec:\s*([\d\.]*)");

            if (rpsMatch.Success && rpsMatch.Groups.Count == 2)
            {
                BenchmarksEventSource.Measure("wrk/rps/mean", double.Parse(rpsMatch.Groups[1].Value));
            }

            var throughputMatch = Regex.Match(output, @"Transfer/sec:\s+([\d\.]+)(\w+)");

            BenchmarksEventSource.Measure("wrk/throughput", ReadThroughput(throughputMatch));

            // Max latency is 3rd number after "Latency "
            var maxLatencyMatch = Regex.Match(output, @"\s+Latency\s+[\d\.]+\w+\s+[\d\.]+\w+\s+([\d\.]+)(\w+)");

            BenchmarksEventSource.Measure("wrk/latency/max", ReadLatency(maxLatencyMatch));

            var requestsCountMatch = Regex.Match(output, @"([\d\.]*) requests in ([\d\.]*)(\w*)");

            BenchmarksEventSource.Measure("wrk/requests", ReadRequests(requestsCountMatch));

            var badResponsesMatch = Regex.Match(output, @"Non-2xx or 3xx responses: ([\d\.]*)");

            BenchmarksEventSource.Measure("wrk/errors/badresponses", ReadBadReponses(badResponsesMatch));

            var socketErrorsMatch = Regex.Match(output, @"Socket errors: connect ([\d\.]*), read ([\d\.]*), write ([\d\.]*), timeout ([\d\.]*)");

            BenchmarksEventSource.Measure("wrk/errors/socketerrors", CountSocketErrors(socketErrorsMatch));

            if (parseLatency)
            {
                BenchmarksEventSource.Register("wrk/latency/50", Operations.Max, Operations.Avg, "Latency 50th (ms)", "Latency 50th (ms)", "n2");
                BenchmarksEventSource.Register("wrk/latency/75", Operations.Max, Operations.Avg, "Latency 75th (ms)", "Latency 50th (ms)", "n2");
                BenchmarksEventSource.Register("wrk/latency/90", Operations.Max, Operations.Avg, "Latency 90th (ms)", "Latency 50th (ms)", "n2");
                BenchmarksEventSource.Register("wrk/latency/99", Operations.Max, Operations.Avg, "Latency 99th (ms)", "Latency 50th (ms)", "n2");

                BenchmarksEventSource.Measure("wrk/latency/50", ReadLatency(Regex.Match(output, string.Format(LatencyPattern, "50%"))));
                BenchmarksEventSource.Measure("wrk/latency/75", ReadLatency(Regex.Match(output, string.Format(LatencyPattern, "75%"))));
                BenchmarksEventSource.Measure("wrk/latency/90", ReadLatency(Regex.Match(output, string.Format(LatencyPattern, "90%"))));
                BenchmarksEventSource.Measure("wrk/latency/99", ReadLatency(Regex.Match(output, string.Format(LatencyPattern, "99%"))));
            }

            return(0);
        }
예제 #9
0
        static async Task <int> Main(string[] args)
        {
            Console.WriteLine("WRK2 Client");
            Console.WriteLine("args: " + String.Join(' ', args));

            var wrk2Filename = await DownloadWrk2Async();

            Console.Write("Measuring first request ... ");
            await MeasureFirstRequest(args);

            // Do we need to parse latency?
            var parseLatency = args.Any(x => x == "--latency" || x == "-L");

            // Extracting duration parameters
            string warmup   = "";
            string duration = "";

            var argsList = args.ToList();

            var durationIndex = argsList.FindIndex(x => String.Equals(x, "-d", StringComparison.OrdinalIgnoreCase));

            if (durationIndex >= 0)
            {
                duration = argsList[durationIndex + 1];
                argsList.RemoveAt(durationIndex);
                argsList.RemoveAt(durationIndex);
            }
            else
            {
                Console.WriteLine("Couldn't find -d argument");
                return(-1);
            }

            var warmupIndex = argsList.FindIndex(x => String.Equals(x, "-w", StringComparison.OrdinalIgnoreCase));

            if (warmupIndex >= 0)
            {
                warmup = argsList[warmupIndex + 1];
                argsList.RemoveAt(warmupIndex);
                argsList.RemoveAt(warmupIndex);
            }

            args = argsList.Select(Quote).ToArray();

            var baseArguments = String.Join(' ', args) + " --print r --format json";

            var process = new Process()
            {
                StartInfo =
                {
                    FileName               = wrk2Filename,
                    RedirectStandardOutput = true,
                    UseShellExecute        = false,
                },
                EnableRaisingEvents = true
            };

            var stringBuilder = new StringBuilder();

            process.OutputDataReceived += (_, e) =>
            {
                if (e != null && e.Data != null)
                {
                    Console.WriteLine(e.Data);

                    lock (stringBuilder)
                    {
                        stringBuilder.AppendLine(e.Data);
                    }
                }
            };

            // Warmup

            if (!String.IsNullOrEmpty(warmup) && warmup != "0s")
            {
                process.StartInfo.Arguments = $" -d {warmup} {baseArguments}";

                Console.WriteLine("> wrk2 " + process.StartInfo.Arguments);

                process.Start();
                process.WaitForExit();

                if (process.ExitCode != 0)
                {
                    return(process.ExitCode);
                }
            }

            lock (stringBuilder)
            {
                stringBuilder.Clear();
            }

            process.StartInfo.Arguments = $" -d {duration} {baseArguments}";

            Console.WriteLine("> wrk2 " + process.StartInfo.Arguments);

            process.Start();

            BenchmarksEventSource.SetChildProcessId(process.Id);

            process.BeginOutputReadLine();
            process.WaitForExit();

            if (process.ExitCode != 0)
            {
                return(process.ExitCode);
            }

            string output;

            lock (stringBuilder)
            {
                output = stringBuilder.ToString();
            }

            BenchmarksEventSource.Register("wrk2/rps/mean", Operations.Max, Operations.Sum, "Requests/sec", "Requests per second", "n0");
            BenchmarksEventSource.Register("wrk2/requests", Operations.Max, Operations.Sum, "Requests", "Total number of requests", "n0");
            BenchmarksEventSource.Register("wrk2/latency/mean", Operations.Max, Operations.Sum, "Mean latency (ms)", "Mean latency (ms)", "n2");
            BenchmarksEventSource.Register("wrk2/latency/max", Operations.Max, Operations.Sum, "Max latency (ms)", "Max latency (ms)", "n2");
            BenchmarksEventSource.Register("wrk2/errors/badresponses", Operations.Max, Operations.Sum, "Bad responses", "Non-2xx or 3xx responses", "n0");
            BenchmarksEventSource.Register("wrk2/errors/socketerrors", Operations.Max, Operations.Sum, "Socket errors", "Socket errors", "n0");

            var rpsMatch = Regex.Match(output, @"Requests/sec:\s*([\d\.]*)");

            if (rpsMatch.Success && rpsMatch.Groups.Count == 2)
            {
                BenchmarksEventSource.Measure("wrk2/rps/mean", double.Parse(rpsMatch.Groups[1].Value));
            }

            const string LatencyPattern = @"\s+{0}\s*([\d\.]+)([a-z]+)";

            var avgLatencyMatch = Regex.Match(output, String.Format(LatencyPattern, "Latency"));

            BenchmarksEventSource.Measure("wrk2/latency/mean", ReadLatency(avgLatencyMatch));

            // Max latency is 3rd number after "Latency "
            var maxLatencyMatch = Regex.Match(output, @"\s+Latency\s+[\d\.]+\w+\s+[\d\.]+\w+\s+([\d\.]+)(\w+)");

            BenchmarksEventSource.Measure("wrk2/latency/max", ReadLatency(maxLatencyMatch));

            var requestsCountMatch = Regex.Match(output, @"([\d\.]*) requests in ([\d\.]*)(\w*)");

            BenchmarksEventSource.Measure("wrk2/requests", ReadRequests(requestsCountMatch));

            var badResponsesMatch = Regex.Match(output, @"Non-2xx or 3xx responses: ([\d\.]*)");

            BenchmarksEventSource.Measure("wrk2/errors/badresponses", ReadBadReponses(badResponsesMatch));

            var socketErrorsMatch = Regex.Match(output, @"Socket errors: connect ([\d\.]*), read ([\d\.]*), write ([\d\.]*), timeout ([\d\.]*)");

            BenchmarksEventSource.Measure("wrk2/errors/socketerrors", CountSocketErrors(socketErrorsMatch));

            if (parseLatency)
            {
                BenchmarksEventSource.Register("wrk2/latency/50", Operations.Max, Operations.Avg, "Latency 50th (ms)", "Latency 50th (ms)", "n2");
                BenchmarksEventSource.Register("wrk2/latency/75", Operations.Max, Operations.Avg, "Latency 75th (ms)", "Latency 50th (ms)", "n2");
                BenchmarksEventSource.Register("wrk2/latency/90", Operations.Max, Operations.Avg, "Latency 90th (ms)", "Latency 50th (ms)", "n2");
                BenchmarksEventSource.Register("wrk2/latency/99", Operations.Max, Operations.Avg, "Latency 99th (ms)", "Latency 50th (ms)", "n2");
                BenchmarksEventSource.Register("wrk2/latency/99.9", Operations.Max, Operations.Avg, "Latency 99.9th (ms)", "Latency 50th (ms)", "n2");
                BenchmarksEventSource.Register("wrk2/latency/99.99", Operations.Max, Operations.Avg, "Latency 99.99th (ms)", "Latency 50th (ms)", "n2");
                BenchmarksEventSource.Register("wrk2/latency/99.999", Operations.Max, Operations.Avg, "Latency 99.999th (ms)", "Latency 50th (ms)", "n2");
                BenchmarksEventSource.Register("wrk2/latency/100", Operations.Max, Operations.Avg, "Latency 100th (ms)", "Latency 50th (ms)", "n2");
                BenchmarksEventSource.Register("wrk2/latency/distribution", Operations.All, Operations.All, "Latency distribution", "Latency distribution", "json");

                BenchmarksEventSource.Measure("wrk2/latency/50", ReadLatency(Regex.Match(output, String.Format(LatencyPattern, "50\\.000%"))));
                BenchmarksEventSource.Measure("wrk2/latency/75", ReadLatency(Regex.Match(output, String.Format(LatencyPattern, "75\\.000%"))));
                BenchmarksEventSource.Measure("wrk2/latency/90", ReadLatency(Regex.Match(output, String.Format(LatencyPattern, "90\\.000%"))));
                BenchmarksEventSource.Measure("wrk2/latency/99", ReadLatency(Regex.Match(output, String.Format(LatencyPattern, "99\\.000%"))));
                BenchmarksEventSource.Measure("wrk2/latency/99.9", ReadLatency(Regex.Match(output, String.Format(LatencyPattern, "99\\.900%"))));
                BenchmarksEventSource.Measure("wrk2/latency/99.99", ReadLatency(Regex.Match(output, String.Format(LatencyPattern, "99\\.990%"))));
                BenchmarksEventSource.Measure("wrk2/latency/99.999", ReadLatency(Regex.Match(output, String.Format(LatencyPattern, "99\\.999%"))));
                BenchmarksEventSource.Measure("wrk2/latency/100", ReadLatency(Regex.Match(output, String.Format(LatencyPattern, "100\\.000%"))));

                using (var sr = new StringReader(output))
                {
                    var line = "";

                    do
                    {
                        line = sr.ReadLine();
                    } while (line != null && !line.Contains("Detailed Percentile spectrum:"));

                    var doc = new JArray();

                    if (line != null)
                    {
                        sr.ReadLine();
                        sr.ReadLine();

                        line = sr.ReadLine();

                        while (line != null && !line.StartsWith("#"))
                        {
                            Console.WriteLine("Analyzing: " + line);

                            var values = line.Split(' ', StringSplitOptions.RemoveEmptyEntries);
                            doc.Add(
                                new JObject(
                                    new JProperty("latency_us", decimal.Parse(values[0], CultureInfo.InvariantCulture)),
                                    new JProperty("count", decimal.Parse(values[2], CultureInfo.InvariantCulture)),
                                    new JProperty("percentile", decimal.Parse(values[1], CultureInfo.InvariantCulture))
                                    ));

                            line = sr.ReadLine();
                        }
                    }

                    BenchmarksEventSource.Measure("wrk2/latency/distribution", doc.ToString());
                }
            }

            return(0);
        }
예제 #10
0
        static int RunCore(string fileName, string[] args, bool parseLatency)
        {
            // Extracting duration parameters
            string warmup   = "";
            string duration = "";

            var argsList = args.ToList();

            var durationIndex = argsList.FindIndex(x => String.Equals(x, "-d", StringComparison.OrdinalIgnoreCase));

            if (durationIndex >= 0)
            {
                duration = argsList[durationIndex + 1];
                argsList.RemoveAt(durationIndex);
                argsList.RemoveAt(durationIndex);
            }
            else
            {
                Console.WriteLine("Couldn't find -d argument");
                return(-1);
            }

            var warmupIndex = argsList.FindIndex(x => String.Equals(x, "-w", StringComparison.OrdinalIgnoreCase));

            if (warmupIndex >= 0)
            {
                warmup = argsList[warmupIndex + 1];
                argsList.RemoveAt(warmupIndex);
                argsList.RemoveAt(warmupIndex);
            }

            args = argsList.Select(Quote).ToArray();

            var baseArguments = String.Join(' ', args);

            var process = new Process()
            {
                StartInfo =
                {
                    FileName               = fileName,
                    RedirectStandardOutput = true,
                    UseShellExecute        = false,
                },
                EnableRaisingEvents = true
            };

            var stringBuilder = new StringBuilder();

            process.OutputDataReceived += (_, e) =>
            {
                if (e != null && e.Data != null)
                {
                    Console.WriteLine(e.Data);

                    lock (stringBuilder)
                    {
                        stringBuilder.AppendLine(e.Data);
                    }
                }
            };

            // Warmup

            if (!String.IsNullOrEmpty(warmup) && warmup != "0s")
            {
                process.StartInfo.Arguments = $"-d {warmup} {baseArguments}";

                Console.WriteLine("> wrk " + process.StartInfo.Arguments);

                process.Start();
                process.WaitForExit();

                if (process.ExitCode != 0)
                {
                    return(process.ExitCode);
                }
            }
            else
            {
                Console.WriteLine("Warmup skipped");
            }

            lock (stringBuilder)
            {
                stringBuilder.Clear();
            }

            if (!String.IsNullOrEmpty(duration) && duration != "0s")
            {
                process.StartInfo.Arguments = $"-d {duration} {baseArguments}";

                Console.WriteLine("> wrk " + process.StartInfo.Arguments);

                process.Start();

                BenchmarksEventSource.SetChildProcessId(process.Id);

                process.BeginOutputReadLine();
                process.WaitForExit();

                if (process.ExitCode != 0)
                {
                    return(process.ExitCode);
                }

                string output;

                lock (stringBuilder)
                {
                    output = stringBuilder.ToString();
                }

                BenchmarksEventSource.Register("wrk/rps/mean;http/rps/mean", Operations.Max, Operations.Sum, "Requests/sec", "Requests per second", "n0");
                BenchmarksEventSource.Register("wrk/requests;http/requests", Operations.Max, Operations.Sum, "Requests", "Total number of requests", "n0");
                BenchmarksEventSource.Register("wrk/latency/mean;http/latency/mean", Operations.Max, Operations.Avg, "Mean latency (ms)", "Mean latency (ms)", "n2");
                BenchmarksEventSource.Register("wrk/latency/max;http/latency/max", Operations.Max, Operations.Max, "Max latency (ms)", "Max latency (ms)", "n2");
                BenchmarksEventSource.Register("wrk/errors/badresponses;http/requests/badresponses", Operations.Max, Operations.Sum, "Bad responses", "Non-2xx or 3xx responses", "n0");
                BenchmarksEventSource.Register("wrk/errors/socketerrors;http/requests/errors", Operations.Max, Operations.Sum, "Socket errors", "Socket errors", "n0");
                BenchmarksEventSource.Register("wrk/throughput;http/throughput", Operations.Max, Operations.Sum, "Read throughput (MB/s)", "Read throughput (MB/s)", "n2");

                /* Sample output
                 * > wrk -d 15s -c 1024 http://10.0.0.102:5000/plaintext --latency -t 32
                 *  Running 15s test @ http://10.0.0.102:5000/plaintext
                 *  32 threads and 1024 connections
                 *  Thread Stats   Avg      Stdev     Max   +/- Stdev
                 *      Latency     0.93ms    1.55ms  63.85ms   97.35%
                 *      Req/Sec   364.39k    34.02k    1.08M    89.87%
                 *  Latency Distribution
                 *      50%  717.00us
                 *      75%    1.05ms
                 *      90%    1.47ms
                 *      99%    6.80ms
                 *  174818486 requests in 15.10s, 20.51GB read
                 *  Requests/sec: 11577304.21
                 *  Transfer/sec:      1.36GB
                 */
                const string LatencyPattern = @"\s+{0}\s+([\d\.]+)(\w+)";

                var latencyMatch = Regex.Match(output, String.Format(LatencyPattern, "Latency"));
                BenchmarksEventSource.Measure("wrk/latency/mean;http/latency/mean", ReadLatency(latencyMatch));

                var rpsMatch = Regex.Match(output, @"Requests/sec:\s*([\d\.]*)");
                if (rpsMatch.Success && rpsMatch.Groups.Count == 2)
                {
                    BenchmarksEventSource.Measure("wrk/rps/mean;http/rps/mean", double.Parse(rpsMatch.Groups[1].Value));
                }

                var throughputMatch = Regex.Match(output, @"Transfer/sec:\s+([\d\.]+)(\w+)");
                BenchmarksEventSource.Measure("wrk/throughput;http/throughput", ReadThroughput(throughputMatch));

                // Max latency is 3rd number after "Latency "
                var maxLatencyMatch = Regex.Match(output, @"\s+Latency\s+[\d\.]+\w+\s+[\d\.]+\w+\s+([\d\.]+)(\w+)");
                BenchmarksEventSource.Measure("wrk/latency/max;http/latency/max", ReadLatency(maxLatencyMatch));

                var requestsCountMatch = Regex.Match(output, @"([\d\.]*) requests in ([\d\.]*)(\w*)");
                BenchmarksEventSource.Measure("wrk/requests;http/requests", ReadRequests(requestsCountMatch));

                var badResponsesMatch = Regex.Match(output, @"Non-2xx or 3xx responses: ([\d\.]*)");
                BenchmarksEventSource.Measure("wrk/errors/badresponses;http/requests/badresponses", ReadBadResponses(badResponsesMatch));

                var socketErrorsMatch = Regex.Match(output, @"Socket errors: connect ([\d\.]*), read ([\d\.]*), write ([\d\.]*), timeout ([\d\.]*)");
                BenchmarksEventSource.Measure("wrk/errors/socketerrors;http/requests/errors", CountSocketErrors(socketErrorsMatch));

                if (parseLatency)
                {
                    BenchmarksEventSource.Register("wrk/latency/50;http/latency/50", Operations.Max, Operations.Max, "Latency 50th (ms)", "Latency 50th (ms)", "n2");
                    BenchmarksEventSource.Register("wrk/latency/75;http/latency/75", Operations.Max, Operations.Max, "Latency 75th (ms)", "Latency 75th (ms)", "n2");
                    BenchmarksEventSource.Register("wrk/latency/90;http/latency/90", Operations.Max, Operations.Max, "Latency 90th (ms)", "Latency 90th (ms)", "n2");
                    BenchmarksEventSource.Register("wrk/latency/99;http/latency/99", Operations.Max, Operations.Max, "Latency 99th (ms)", "Latency 99th (ms)", "n2");

                    BenchmarksEventSource.Measure("wrk/latency/50;http/latency/50", ReadLatency(Regex.Match(output, string.Format(LatencyPattern, "50%"))));
                    BenchmarksEventSource.Measure("wrk/latency/75;http/latency/75", ReadLatency(Regex.Match(output, string.Format(LatencyPattern, "75%"))));
                    BenchmarksEventSource.Measure("wrk/latency/90;http/latency/90", ReadLatency(Regex.Match(output, string.Format(LatencyPattern, "90%"))));
                    BenchmarksEventSource.Measure("wrk/latency/99;http/latency/99", ReadLatency(Regex.Match(output, string.Format(LatencyPattern, "99%"))));
                }
            }
            else
            {
                Console.WriteLine("Benchmark skipped");
            }

            return(0);
        }
예제 #11
0
        static async Task <int> Main(string[] args)
        {
            Console.WriteLine("Bombardier Client");
            Console.WriteLine("args: " + String.Join(' ', args));

            Console.Write("Measuring first request ... ");
            await MeasureFirstRequest(args);

            // Extracting parameters
            var argsList = args.ToList();

            TryGetArgumentValue("-w", argsList, out int warmup);
            TryGetArgumentValue("-d", argsList, out int duration);
            TryGetArgumentValue("-n", argsList, out int requests);

            if (duration == 0 && requests == 0)
            {
                Console.WriteLine("Couldn't find valid -d and -n arguments (integers)");
                return(-1);
            }

            TryGetArgumentValue("-w", argsList, out warmup);

            args = argsList.ToArray();

            string bombardierUrl = null;

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                bombardierUrl = "https://github.com/codesenberg/bombardier/releases/download/v1.2.4/bombardier-windows-amd64.exe";
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                bombardierUrl = "https://github.com/codesenberg/bombardier/releases/download/v1.2.4/bombardier-linux-amd64";
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                bombardierUrl = "https://github.com/codesenberg/bombardier/releases/download/v1.2.4/bombardier-darwin-amd64";
            }
            else
            {
                Console.WriteLine("Unsupported platform");
                return(-1);
            }

            var cacheFolder = Path.Combine(Path.GetTempPath(), ".crank");

            if (!Directory.Exists(cacheFolder))
            {
                Directory.CreateDirectory(cacheFolder);
            }

            var bombardierFileName = Path.Combine(cacheFolder, Path.GetFileName(bombardierUrl));

            Console.WriteLine($"Downloading bombardier from {bombardierUrl} to {bombardierFileName}");

            using (var downloadStream = await _httpClient.GetStreamAsync(bombardierUrl))
                using (var fileStream = File.Create(bombardierFileName))
                {
                    await downloadStream.CopyToAsync(fileStream);
                }

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ||
                RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                Console.WriteLine($"Setting execute permission on executable {bombardierFileName}");
                Process.Start("chmod", "+x " + bombardierFileName);
            }

            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                Console.WriteLine($"Allow running bombardier");
                Process.Start("spctl", "--add " + bombardierFileName);
            }

            args = argsList.Select(Quote).ToArray();

            var baseArguments = String.Join(' ', args) + " --print r --format json";

            var process = new Process()
            {
                StartInfo =
                {
                    FileName               = bombardierFileName,
                    RedirectStandardOutput = true,
                    UseShellExecute        = false,
                },
                EnableRaisingEvents = true
            };

            var stringBuilder = new StringBuilder();

            process.OutputDataReceived += (_, e) =>
            {
                if (e != null && e.Data != null)
                {
                    Console.WriteLine(e.Data);

                    lock (stringBuilder)
                    {
                        stringBuilder.AppendLine(e.Data);
                    }
                }
            };

            // Warmup

            if (warmup > 0)
            {
                process.StartInfo.Arguments = $" -d {warmup}s {baseArguments}";

                Console.WriteLine("> bombardier " + process.StartInfo.Arguments);

                await StartProcessWithRetriesAsync(process);

                process.WaitForExit();

                if (process.ExitCode != 0)
                {
                    return(process.ExitCode);
                }
            }

            lock (stringBuilder)
            {
                stringBuilder.Clear();
            }

            process.StartInfo.Arguments =
                requests > 0
                    ? $" -n {requests} {baseArguments}"
                    : $" -d {duration}s {baseArguments}";

            Console.WriteLine("> bombardier " + process.StartInfo.Arguments);

            await StartProcessWithRetriesAsync(process);

            BenchmarksEventSource.SetChildProcessId(process.Id);

            process.BeginOutputReadLine();
            process.WaitForExit();

            if (process.ExitCode != 0)
            {
                return(process.ExitCode);
            }

            string output;

            lock (stringBuilder)
            {
                output = stringBuilder.ToString();
            }

            var document = JObject.Parse(output);

            BenchmarksEventSource.Register("bombardier/requests", Operations.Max, Operations.Sum, "Requests", "Total number of requests", "n0");
            BenchmarksEventSource.Register("bombardier/badresponses", Operations.Max, Operations.Sum, "Bad responses", "Non-2xx or 3xx responses", "n0");

            BenchmarksEventSource.Register("bombardier/latency/mean", Operations.Max, Operations.Sum, "Mean latency (us)", "Mean latency (us)", "n0");
            BenchmarksEventSource.Register("bombardier/latency/max", Operations.Max, Operations.Sum, "Max latency (us)", "Max latency (us)", "n0");

            BenchmarksEventSource.Register("bombardier/rps/mean", Operations.Max, Operations.Sum, "Requests/sec", "Requests per second", "n0");
            BenchmarksEventSource.Register("bombardier/rps/max", Operations.Max, Operations.Sum, "Requests/sec (max)", "Max requests per second", "n0");
            BenchmarksEventSource.Register("bombardier/throughput", Operations.Max, Operations.Sum, "Read throughput (MB/s)", "Read throughput (MB/s)", "n2");

            BenchmarksEventSource.Register("bombardier/raw", Operations.All, Operations.All, "Raw results", "Raw results", "json");

            var total =
                document["result"]["req1xx"].Value <long>()
                + document["result"]["req2xx"].Value <long>()
                + document["result"]["req3xx"].Value <long>()
                + document["result"]["req3xx"].Value <long>()
                + document["result"]["req4xx"].Value <long>()
                + document["result"]["req5xx"].Value <long>()
                + document["result"]["others"].Value <long>();

            var success = document["result"]["req2xx"].Value <long>() + document["result"]["req3xx"].Value <long>();

            BenchmarksEventSource.Measure("bombardier/requests", total);
            BenchmarksEventSource.Measure("bombardier/badresponses", total - success);

            BenchmarksEventSource.Measure("bombardier/latency/mean", document["result"]["latency"]["mean"].Value <double>());
            BenchmarksEventSource.Measure("bombardier/latency/max", document["result"]["latency"]["max"].Value <double>());

            BenchmarksEventSource.Measure("bombardier/rps/max", document["result"]["rps"]["max"].Value <double>());
            BenchmarksEventSource.Measure("bombardier/rps/mean", document["result"]["rps"]["mean"].Value <double>());

            BenchmarksEventSource.Measure("bombardier/raw", output);

            var bytesPerSecond = document["result"]["bytesRead"].Value <long>() / document["result"]["timeTakenSeconds"].Value <double>();

            // B/s to MB/s
            BenchmarksEventSource.Measure("bombardier/throughput", bytesPerSecond / 1024 / 1024);

            return(0);
        }
예제 #12
0
 public static void MeasureAndRegister(string name, double value, string description, string format = "n2")
 {
     BenchmarksEventSource.Register(name, Operations.First, Operations.First, description, description, format);
     BenchmarksEventSource.Measure(name, value);
 }