public void Run(IBenchmarkResultWriter export) { var timer = new Stopwatch(); // Running symmetric tests. var results = new List <BenchmarkResult>(); foreach (var file in collection.Get(true)) { Run(file, timer, results); } export.Add("symmetric", results); // Running non-symmetric tests. results = new List <BenchmarkResult>(); foreach (var file in collection.Get(false)) { Run(file, timer, results); } export.Add("general", results); }
/// <summary> /// Run the benchmark. /// </summary> public void Run() { PrintDebug("Started benchmark: " + this); ValidateArguments(); if (ResultWriter.ToLower().Equals(ResultWriterConsole)) { _writer = new BenchmarkConsoleResultWriter(); } else { _writer = new BenchmarkFileResultWriter(); } OnStarted(); PrintDebug("Benchmark setup finished."); try { _descs = new List <BenchmarkOperationDescriptor>(); GetDescriptors(_descs); if (_descs.Count == 0) { throw new Exception("No tasks provided for benchmark."); } // Initialize writer. var opNames = new List <string>(_descs.Select(desc => desc.Name)); PrintDebug(() => { var sb = new StringBuilder("Operations: "); foreach (var opName in opNames) { sb.Append(opName).Append(" "); } return(sb.ToString()); }); _writer.Initialize(this, opNames); PrintDebug("Initialized result writer."); // Start worker threads. _tasks = new List <BenchmarkTask>(Threads); PrintDebug("Starting worker threads: " + Threads); for (var i = 0; i < Threads; i++) { var task = new BenchmarkTask(this, _descs); _tasks.Add(task); new Thread(task.Run).Start(); } PrintDebug("Waiting worker threads to start: " + Threads); // Await for all threads to start in spin loop. while (Thread.VolatileRead(ref _readyThreads) < Threads) { Thread.Sleep(10); } PrintDebug("Worker threads started: " + Threads); // Start throughput writer thread. var writerThread = new Thread(new ThroughputTask(this).Run) { IsBackground = true }; writerThread.Start(); PrintDebug("Started throughput writer thread."); // Start warmup thread if needed. if (Warmup > 0) { var thread = new Thread(new WarmupTask(this, Warmup).Run) { IsBackground = true }; thread.Start(); PrintDebug("Started warmup timeout thread: " + Warmup); } else { _warmup = false; } _barrier = new Barrier(Threads, b => { Console.WriteLine("Warmup finished."); _totalWatch.Start(); }); // Start timeout thread if needed. if (Duration > 0) { if (Operations > 0) { PrintDebug("Duration argument is ignored because operations number is set: " + Operations); } else { var thread = new Thread(new TimeoutTask(this, Warmup + Duration).Run) { IsBackground = true }; thread.Start(); PrintDebug("Started duration timeout thread: " + Duration); } } // Let workers start execution. _start = true; // Await workers completion. PrintDebug("Awaiting worker threads completion."); Monitor.Enter(this); try { while (_finishedThreads < Threads) { Monitor.Wait(this); } } finally { Monitor.Exit(this); } PrintDebug("Worker threads completed."); } finally { OnFinished(); _totalWatch.Stop(); PrintDebug("Tear down invoked."); if (PrintThroughputInfo()) { var avgThroughput = _totalWatch.ElapsedMilliseconds == 0 ? 0 : _curOps * 1000 / _totalWatch.ElapsedMilliseconds; var avgLatency = _curOps == 0 ? 0 : (double)_totalWatch.ElapsedMilliseconds * Threads / _curOps; Console.WriteLine("Finishing benchmark [name=" + GetType().Name + ", time=" + _totalWatch.ElapsedMilliseconds + "ms, ops=" + _curOps + ", threads=" + Threads + ", avgThroughput=" + avgThroughput + ", avgLatency=" + string.Format("{0:0.000}ms", avgLatency) + ']'); } else { Console.WriteLine("Finishing benchmark [name=" + GetType().Name + ", time=" + _totalWatch.ElapsedMilliseconds + "ms, ops=" + Operations + ", threads=" + Threads + ']'); } } _percentiles = new Dictionary <string, long[]>(_descs.Count); foreach (var desc in _descs) { _percentiles[desc.Name] = new long[ResultBucketCount]; } foreach (var task in _tasks) { task.CollectPercentiles(_percentiles); } foreach (var percentile in _percentiles) { _writer.WritePercentiles(percentile.Key, ResultBucketInterval, percentile.Value); } _writer.Commit(); PrintDebug("Results committed to output writer."); }
/// <summary> /// Run the benchmark. /// </summary> public void Run() { PrintDebug("Started benchmark: " + this); ValidateArguments(); if (ResultWriter.ToLower().Equals(ResultWriterConsole)) _writer = new BenchmarkConsoleResultWriter(); else _writer = new BenchmarkFileResultWriter(); OnStarted(); PrintDebug("Benchmark setup finished."); try { _descs = new List<BenchmarkOperationDescriptor>(); GetDescriptors(_descs); if (_descs.Count == 0) throw new Exception("No tasks provided for benchmark."); // Initialize writer. var opNames = new List<string>(_descs.Select(desc => desc.Name)); PrintDebug(() => { var sb = new StringBuilder("Operations: "); foreach (var opName in opNames) sb.Append(opName).Append(" "); return sb.ToString(); }); _writer.Initialize(this, opNames); PrintDebug("Initialized result writer."); // Start worker threads. _tasks = new List<BenchmarkTask>(Threads); PrintDebug("Starting worker threads: " + Threads); for (var i = 0; i < Threads; i++) { var task = new BenchmarkTask(this, _descs); _tasks.Add(task); new Thread(task.Run).Start(); } PrintDebug("Waiting worker threads to start: " + Threads); // Await for all threads to start in spin loop. while (Thread.VolatileRead(ref _readyThreads) < Threads) Thread.Sleep(10); PrintDebug("Worker threads started: " + Threads); // Start throughput writer thread. var writerThread = new Thread(new ThroughputTask(this).Run) {IsBackground = true}; writerThread.Start(); PrintDebug("Started throughput writer thread."); // Start warmup thread if needed. if (Warmup > 0) { var thread = new Thread(new WarmupTask(this, Warmup).Run) {IsBackground = true}; thread.Start(); PrintDebug("Started warmup timeout thread: " + Warmup); } else _warmup = false; _barrier = new Barrier(Threads, b => { Console.WriteLine("Warmup finished."); _totalWatch.Start(); }); // Start timeout thread if needed. if (Duration > 0) { if (Operations > 0) PrintDebug("Duration argument is ignored because operations number is set: " + Operations); else { var thread = new Thread(new TimeoutTask(this, Warmup + Duration).Run) {IsBackground = true}; thread.Start(); PrintDebug("Started duration timeout thread: " + Duration); } } // Let workers start execution. _start = true; // Await workers completion. PrintDebug("Awaiting worker threads completion."); Monitor.Enter(this); try { while (_finishedThreads < Threads) Monitor.Wait(this); } finally { Monitor.Exit(this); } PrintDebug("Worker threads completed."); } finally { OnFinished(); _totalWatch.Stop(); PrintDebug("Tear down invoked."); if (PrintThroughputInfo()) { var avgThroughput = _totalWatch.ElapsedMilliseconds == 0 ? 0 : _curOps*1000/_totalWatch.ElapsedMilliseconds; var avgLatency = _curOps == 0 ? 0 : (double) _totalWatch.ElapsedMilliseconds*Threads/_curOps; Console.WriteLine("Finishing benchmark [name=" + GetType().Name + ", time=" + _totalWatch.ElapsedMilliseconds + "ms, ops=" + _curOps + ", threads=" + Threads + ", avgThroughput=" + avgThroughput + ", avgLatency=" + string.Format("{0:0.000}ms", avgLatency) + ']'); } else { Console.WriteLine("Finishing benchmark [name=" + GetType().Name + ", time=" + _totalWatch.ElapsedMilliseconds + "ms, ops=" + Operations + ", threads=" + Threads + ']'); } } _percentiles = new Dictionary<string, long[]>(_descs.Count); foreach (var desc in _descs) _percentiles[desc.Name] = new long[ResultBucketCount]; foreach (var task in _tasks) task.CollectPercentiles(_percentiles); foreach (var percentile in _percentiles) _writer.WritePercentiles(percentile.Key, ResultBucketInterval, percentile.Value); _writer.Commit(); PrintDebug("Results committed to output writer."); }