private static async Task ExecuteIterationAsync( string rootDir, string resultsPath, string variantName, string solutionName, HttpClient httpClient, int iterations, int maxConcurrency, List <RequestNode> topologicalOrder, int iteration, bool noDependencies) { var logPrefix = $"[{iteration}/{iterations}{(iteration == 0 ? " (warm-up)" : string.Empty)}]"; string requestsFileName; if (variantName == null) { requestsFileName = $"{ReplayLogPrefix}-{solutionName}-{Helper.GetLogTimestamp()}.csv"; } else { requestsFileName = $"{ReplayLogPrefix}-{variantName}-{solutionName}-{Helper.GetLogTimestamp()}.csv"; } var logsDir = Path.Combine(rootDir, "out", "logs"); if (!Directory.Exists(logsDir)) { Directory.CreateDirectory(logsDir); } var requestsPath = Path.Combine(logsDir, requestsFileName); var stopwatch = new Stopwatch(); using (var writer = new BackgroundCsvWriter <ReplayRequestRecord>(requestsPath, gzip: false)) { Console.WriteLine($"{logPrefix} Starting..."); var nodeToTask = new Dictionary <RequestNode, Task>(); var throttle = new SemaphoreSlim(maxConcurrency); var consoleLock = new object(); stopwatch.Start(); foreach (var node in topologicalOrder) { nodeToTask.Add(node, GetRequestTask(nodeToTask, throttle, consoleLock, httpClient, node, writer)); } try { await Task.WhenAll(nodeToTask.Values); } catch (Exception ex) { Console.WriteLine("At least one request failed."); Console.WriteLine(ex.ToString()); } stopwatch.Stop(); Console.WriteLine($"{logPrefix} Completed in {stopwatch.ElapsedMilliseconds}ms."); } CsvUtility.Append(resultsPath, new ReplayResultRecord { TimestampUtc = Helper.GetExcelTimestamp(DateTimeOffset.UtcNow), MachineName = Environment.MachineName, Iteration = iteration, IsWarmUp = iteration == 0, Iterations = iterations, VariantName = variantName, SolutionName = solutionName, RequestCount = topologicalOrder.Count, DurationMs = stopwatch.Elapsed.TotalMilliseconds, MaxConcurrency = maxConcurrency, LogFileName = requestsFileName, Dependencies = !noDependencies, }); }