Ejemplo n.º 1
0
        public ThreadRunner(Func<bool> executionCondition, ThreadResult result, TimingSettings settings, BenchmarkState sharedState, Action test, ITimerFactory timerFactory)
        {
            this.ExecutionCondition = executionCondition;
            this.Result = result;
            this.Settings = settings;
            this.SharedState = sharedState;
            this.Test = test;

            Timer = timerFactory.Create();

            thread = new Thread(Run);
            thread.IsBackground = true;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Runs the benchmark. Does not throw exceptions in case the test function throws one - if
        /// <see cref="TimingSettings.CatchTestExceptions"/> is false, the execution thread will rethrow the exception.
        /// This method sets <see cref="BenchmarkResult.HasErrors"/> to true in case of an exception, so if you have
        /// set <see cref="TimingSettings.CatchTestExceptions"/> to true, check <see cref="BenchmarkResult.HasErrors"/>
        /// afterwards.
        /// </summary>
        /// <param name="test">
        /// Callback function that executes the test once.
        /// </param>
        /// <param name="executionCondition">
        /// Optional callback function that defines whether the test is executed another time. You can use this if you
        /// have a shared state between test runs, e.g. a fixed-size list of inputs and each of them must be only used
        /// once.
        /// </param>
        /// <param name="resultName">
        /// Optional name you want to assign to the result, e.g. "Run with 10 concurrent threads".
        /// </param>
        /// <returns>
        /// Benchmark results.
        /// </returns>
        public virtual BenchmarkResult RunBenchmark(Action test, Func<bool> executionCondition = null, string resultName = null)
        {
            if(test == null)
                throw new ArgumentNullException("test");

            EnsureCorrectSettings();

            var timer = TimerFactory.Create();

            timer.Start();

            var result = new BenchmarkResult
            {
                BenchmarkName = this.Name,
                ExceptionMode = Settings.ExceptionMode,
                Mode = Settings.Mode,
                ResultName = resultName
            };

            var concurrency = Settings.Concurrency;
            var sharedState = new BenchmarkState(TimerFactory);
            var threads = new ThreadRunner[concurrency];
            result.ThreadResults = new ThreadResult[concurrency];

            for(int i = 0; i < concurrency; ++i)
            {
                result.ThreadResults[i] = new ThreadResult { ExceptionMode = Settings.ExceptionMode };
                threads[i] = new ThreadRunner(executionCondition, result.ThreadResults[i], Settings, sharedState, test, TimerFactory);
            }

            // Start the actual benchmark in background thread(s)
            sharedState.TimerFromBeginning.Start();
            for(int i = 0; i < concurrency; ++i)
                threads[i].Start();

            // Wait for all threads to finish
            for(int i = 0; i < concurrency; ++i)
                threads[i].Join();

            // Final value of this timer is unused
            sharedState.TimerFromBeginning.Stop();

            timer.Stop();

            // Propagate exceptions if any
            foreach(var threadResult in result.ThreadResults)
                if(threadResult.FirstUncountedException != null)
                {
                    result.FirstUncountedException = threadResult.FirstUncountedException;
                    break;
                }

            if(Settings.ExceptionMode == ExceptionMode.COUNT)
                foreach(var threadResult in result.ThreadResults)
                    if(threadResult.FirstCountedException != null)
                    {
                        result.FirstCountedException = threadResult.FirstCountedException;
                        break;
                    }

            var elapsed = timer.Elapsed;

            result.CompleteElapsedTime = elapsed;
            result.CompletedExecutions = sharedState.CompletedExecutions;

            return result;
        }