public Task RunAsync(TimeSpan duration, CancellationToken token) { // Can't run for more than 24 days because the maximum number of milliseconds in a Int32 is 24.8 days. Guard.ArgumentInRange(duration.TotalDays, 0, 24, nameof(duration)); DateTime endTime = DateTime.Now.Add(duration); Stopwatch sw = new Stopwatch(); // Start a failure test scenario. FaultTest ft = new FaultTest(FaultTest.TestType.Failover, duration); Task ftt = ft.RunAsync(_serviceUri, ProgressHandler); // Start a read test scenario. ReadTest <T> readTest = new ReadTest <T>(1, _numThreads, _maxRequests, _outputFileName, token); Task rtt = ExecuteTestsAsync(sw, duration, readTest.ReadThreadProc); long readTestCount = 0; long rtd = sw.ElapsedMilliseconds; // Start a write test scenario. WriteTest <T> writeTest = new WriteTest <T>(1, _numThreads, _maxRequests, _outputFileName, _createProc, token); Task wtt = ExecuteTestsAsync(sw, duration, writeTest.WriteThreadProc); long writeTestCount = 0; long wtd = sw.ElapsedMilliseconds; // Handle task completion until the duration is exceeded. while (endTime > DateTime.Now) { token.ThrowIfCancellationRequested(); int timeoutMS = (int)(endTime.Subtract(DateTime.Now).TotalMilliseconds); try { // Wait for a task to complete. if (-1 == Task.WaitAny(new[] { ftt, rtt, wtt }, timeoutMS, token)) { Console.WriteLine("Timed out waiting for the tasks to complete."); } if (TaskStatus.RanToCompletion == ftt.Status) { ftt = ft.RunAsync(_serviceUri, ProgressHandler); } if (TaskStatus.RanToCompletion == rtt.Status) // rtt - output read data to the local file and start another read test. { readTest.OutputPerformenceRunFile(sw.ElapsedMilliseconds - rtd, CalculateRPS(_maxRequests, sw.ElapsedMilliseconds, rtd)); rtt = ExecuteTestsAsync(sw, duration, readTest.ReadThreadProc); rtd = sw.ElapsedMilliseconds; readTestCount++; } if (TaskStatus.RanToCompletion == wtt.Status) // wtt - output write data to the local file and start another write test. { writeTest.OutputPerformenceRunFile(sw.ElapsedMilliseconds - wtd, CalculateRPS(_maxRequests, sw.ElapsedMilliseconds, wtd)); wtt = ExecuteTestsAsync(sw, duration, writeTest.WriteThreadProc); wtd = sw.ElapsedMilliseconds; writeTestCount++; } } catch (Exception ex) { Console.WriteLine("Exception: {0} at {1}", ex.Message, ex.StackTrace); } Console.Write($"\rMinutes remaining: {Math.Max(0, (endTime.Subtract(DateTime.Now)).TotalMinutes):N2} Fault progress: {_faultProgress:N0}%\tRead test count: {readTestCount:N}\tWrite test count: {writeTestCount:N}"); } return(Task.FromResult(true)); }
static void Main(string[] args) { if (false == ParseCommandLine(args)) { ShowHelp(); Console.ReadLine(); return; } // Initialize variables. DiscoverServiceParametersAsync().GetAwaiter().GetResult(); CancellationTokenSource cts = new CancellationTokenSource(); do { int temp; TimeSpan duration; ReadTest <Item> rt; WriteTest <Item> wt; Stopwatch sw = new Stopwatch(); const int MinimumMinutes = 60; // If not arguments were specified, go interactive. if (0 == args.Length) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("\nCommands: [C]ount, [D]efaults, [E]mpty, [F]aults, [I]tems, [L]onghaul, pri[O]rities, [P]eek, [R]ead test, R/W [T]est, [W]rite test or e[X]it? "); Console.WriteLine($"\tThreads: {_threads}\tRequests: {_requests}\tBatch: {_batch}\tSize: {_instanceBytes}"); Console.ResetColor(); ConsoleKeyInfo keyInfo = Console.ReadKey(true); Console.WriteLine(); switch (keyInfo.Key) { case ConsoleKey.C: GetItemCountAsync().Wait(); break; case ConsoleKey.D: Console.WriteLine($"Enter the number of threads. Current value is {_threads}: "); _threads = int.TryParse(Console.ReadLine(), out temp) ? temp : _threads; Console.WriteLine($"Enter the number of requests. Current value is {_requests}: "); _requests = int.TryParse(Console.ReadLine(), out temp) ? temp : _requests; Console.WriteLine($"Enter the size of a batch. Current value is {_batch}: "); _batch = int.TryParse(Console.ReadLine(), out temp) ? temp : _batch; break; case ConsoleKey.E: //EmptyPartition(); break; case ConsoleKey.F: Console.WriteLine("[C]haos or [F]ailover test: "); keyInfo = Console.ReadKey(); Console.WriteLine($"Enter the test duration in minutes ({MinimumMinutes} minute minimum): "); duration = TimeSpan.FromMinutes(int.Parse(Console.ReadLine())); if (duration > TimeSpan.FromMinutes(MinimumMinutes)) { var ft = new FaultTest((keyInfo.Key == ConsoleKey.C) ? FaultTest.TestType.Chaos : FaultTest.TestType.Failover, duration); ft.RunAsync(_serviceUri).GetAwaiter().GetResult(); } break; case ConsoleKey.I: GetItems(); break; case ConsoleKey.L: Console.WriteLine("Enter the test duration in minutes: "); duration = TimeSpan.FromMinutes(int.Parse(Console.ReadLine())); if (duration > TimeSpan.Zero) { var lh = new Longhaul <Item>(_threads, _requests, _serviceUri, c_ListenerName, CreateRandomInstance); lh.RunAsync(duration, cts.Token).GetAwaiter().GetResult(); } break; case ConsoleKey.O: GetPriorityCount(); break; case ConsoleKey.P: Peek(); break; case ConsoleKey.R: rt = new ReadTest <Item>(_batch, _threads, _requests, c_outputFilename, cts.Token); rt.RunAsync(cts.Token).GetAwaiter().GetResult(); rt = null; break; case ConsoleKey.T: rt = new ReadTest <Item>(_batch, _threads, _requests, c_outputFilename, cts.Token); wt = new WriteTest <Item>(_batch, _threads, _requests, c_outputFilename, CreateRandomInstance, cts.Token); Task.WhenAll(rt.RunAsync(cts.Token), wt.RunAsync(cts.Token)); break; case ConsoleKey.W: wt = new WriteTest <Item>(_batch, _threads, _requests, c_outputFilename, CreateRandomInstance, cts.Token); wt.RunAsync(cts.Token).GetAwaiter().GetResult(); wt = null; break; case ConsoleKey.X: cts.Cancel(); return; } } } while (0 == args.Length); }