예제 #1
0
        private static bool SpinWait(
            Mutex mutex,
            TimeSpan waitTimeout, TimeSpan spinWaitTimeout,
            CompetitionState competitionState)
        {
            if (spinWaitTimeout > waitTimeout)
            {
                spinWaitTimeout = waitTimeout;
            }

            bool result;

            var totalSpinTime = TimeSpan.Zero;
            var waitStopwatch = Stopwatch.StartNew();

            do
            {
                try
                {
                    result = mutex.WaitOne(spinWaitTimeout);

                    if (!result)
                    {
                        competitionState.WriteMessage(
                            MessageSource.Runner, MessageSeverity.Informational,
                            $"Another perftest is running, wait timeout {totalSpinTime} of {waitTimeout}.");
                    }
                    else if (totalSpinTime > TimeSpan.Zero)
                    {
                        competitionState.WriteMessage(
                            MessageSource.Runner, MessageSeverity.Informational,
                            $"Another perftest completed, starting. Wait timeout {totalSpinTime} of {waitTimeout}.");
                    }
                }
                catch (AbandonedMutexException ex)
                {
                    // It's ok to swallow abandoned mutex exception as we have no shared resources but logger output
                    // and the log is protected by FileShare.Read lock
                    // see https://msdn.microsoft.com/en-us/library/system.threading.abandonedmutexexception.aspx
                    // for more detail.
                    competitionState.WriteExceptionMessage(
                        MessageSource.Runner, MessageSeverity.Informational,
                        $"Another perftest aborted, starting. Wait timeout {totalSpinTime} of {waitTimeout}.", ex);

                    result = true;
                    break;
                }

                if (result)
                {
                    break;
                }

                totalSpinTime += spinWaitTimeout;
            }
            // double check, exit by first condition
            while (totalSpinTime < waitTimeout && waitStopwatch.Elapsed < waitTimeout);

            return(result);
        }
예제 #2
0
        // TODO: as a part of CompetitionRunnerBase
        private static bool CheckPreconditions(
            [NotNull] Type benchmarkType,
            bool lockTaken, bool allowDebugBuilds,
            ConcurrentRunBehavior concurrentRunBehavior,
            CompetitionState competitionState)
        {
            if (!lockTaken)
            {
                switch (concurrentRunBehavior)
                {
                case ConcurrentRunBehavior.Lock:
                case ConcurrentRunBehavior.Skip:
                    competitionState.WriteMessage(
                        MessageSource.Runner, MessageSeverity.Warning,
                        "Competition run skipped. Competitions cannot be run in parallel, be sure to disable parallel test execution.");
                    return(false);

                default:
                    throw CodeExceptions.UnexpectedArgumentValue(nameof(concurrentRunBehavior), concurrentRunBehavior);
                }
            }

            if (!allowDebugBuilds && benchmarkType.Assembly.IsDebugAssembly())
            {
                var assembly = benchmarkType.Assembly;
                competitionState.WriteMessage(
                    MessageSource.Runner, MessageSeverity.Warning,
                    $"Competition run skipped. Assembly {assembly.GetName().Name} was build as debug.");

                return(false);
            }

            return(true);
        }
예제 #3
0
        private static void RunCore(Type benchmarkType, CompetitionState competitionState, int maxRunsAllowed)
        {
            var logger = competitionState.Logger;

            while (competitionState.RunsLeft > 0)
            {
                competitionState.PrepareForRun();

                var run          = competitionState.RunNumber;
                var runsExpected = competitionState.RunNumber + competitionState.RunsLeft;
                var runMessage   = competitionState.RunLimitExceeded
                                        ? $"Run {run}, total runs (expected): {runsExpected} (rerun limit exceeded, last run)"
                                        : $"Run {run}, total runs (expected): {runsExpected}";

                using (BeginLogImportant(competitionState.Config))
                {
                    logger.WriteSeparatorLine(runMessage);
                }

                // Running the benchmark
                var summary = BenchmarkRunner.Run(benchmarkType, competitionState.Config);
                competitionState.RunCompleted(summary);

                // TODO: dump them before analyser run?
                WriteValidationMessages(competitionState);

                if (competitionState.HasCriticalErrorsInRun)
                {
                    logger.WriteLineInfo($"{LogImportantInfoPrefix} Breaking competition execution. High severity error occured.");
                    break;
                }

                if (competitionState.RunLimitExceeded)
                {
                    break;
                }

                if (competitionState.RunsLeft > 0)
                {
                    logger.WriteLineInfo($"{LogImportantInfoPrefix} Rerun requested. Runs left: {competitionState.RunsLeft}.");
                }
            }

            // TODO: notify analysers for last run? // Will need to define custom interface, of course.
            // TODO: move to somewhere else?
            if (competitionState.RunLimitExceeded && competitionState.RunsLeft > 0)
            {
                competitionState.WriteMessage(
                    MessageSource.Runner, MessageSeverity.TestError,
                    $"The benchmark run limit ({competitionState.MaxRunsAllowed} runs(s)) exceeded (read log for details). Try to loose competition limits.");
            }
            else if (competitionState.RunNumber > 1)
            {
                competitionState.WriteMessage(
                    MessageSource.Runner, MessageSeverity.Warning,
                    $"The benchmark was run {competitionState.RunNumber} time(s) (read log for details). Try to loose competition limits.");
            }
        }
예제 #4
0
        private static bool CheckPreconditions(
            [NotNull] Type benchmarkType,
            bool lockTaken,
            CompetitionState competitionState)
        {
            var runOptions = competitionState.Options.RunOptions;

            if (!lockTaken)
            {
                switch (runOptions.Concurrent)
                {
                case ConcurrentRunBehavior.Lock:
                case ConcurrentRunBehavior.Skip:
                    competitionState.WriteMessage(
                        MessageSource.Runner, MessageSeverity.Warning,
                        "Competition run skipped. Competitions cannot be run in parallel, be sure to disable parallel test execution.");
                    return(false);

                case ConcurrentRunBehavior.Fail:
                    competitionState.WriteMessage(
                        MessageSource.Runner, MessageSeverity.SetupError,
                        "Competition run failed. Competitions cannot be run in parallel, be sure to disable parallel test execution.");
                    return(false);

                default:
                    throw CodeExceptions.UnexpectedArgumentValue(nameof(runOptions.Concurrent), runOptions.Concurrent);
                }
            }

            if (!runOptions.AllowDebugBuilds && benchmarkType.Assembly.IsDebugAssembly())
            {
                var assembly = benchmarkType.Assembly;
                competitionState.WriteMessage(
                    MessageSource.Runner, MessageSeverity.Warning,
                    $"Competition run skipped. Assembly {assembly.GetName().Name} was build as debug.");

                return(false);
            }

            if (runOptions.ContinuousIntegrationMode)
            {
                competitionState.WriteMessage(
                    MessageSource.Runner, MessageSeverity.Informational,
                    "Competition is run under continuous integration service.");
            }

            return(true);
        }
예제 #5
0
        /// <summary>Writes exception message.</summary>
        /// <param name="competitionState">State of the run.</param>
        /// <param name="messageSource">Source of the message.</param>
        /// <param name="messageSeverity">Severity of the message.</param>
        /// <param name="message">The explanation for the exception.</param>
        /// <param name="ex">The exception to write.</param>
        public static void WriteExceptionMessage(
            [NotNull] this CompetitionState competitionState,
            MessageSource messageSource, MessageSeverity messageSeverity,
            [NotNull] string message,
            [NotNull] Exception ex)
        {
            Code.NotNullNorEmpty(message, nameof(message));
            Code.NotNull(ex, nameof(ex));

            competitionState.WriteMessage(
                messageSource, messageSeverity,
                $"{message} Exception: {ex.Message}",
                ex.ToDiagnosticString());
        }
예제 #6
0
        /// <summary>Reports analyser warning.</summary>
        /// <param name="competitionState">State of the run.</param>
        /// <param name="warnings">The list the warnings will be added to.</param>
        /// <param name="severity">Severity of the message.</param>
        /// <param name="message">The message.</param>
        /// <param name="report">The report the message belongs to.</param>
        public static void AddAnalyserWarning(
            [NotNull] this CompetitionState competitionState,
            [NotNull] List <IWarning> warnings,
            MessageSeverity severity,
            [NotNull] string message,
            BenchmarkReport report = null)
        {
            Code.NotNull(competitionState, nameof(competitionState));
            Code.NotNull(warnings, nameof(warnings));
            Code.NotNullNorEmpty(message, nameof(message));

            competitionState.WriteMessage(MessageSource.Analyser, severity, message);
            warnings.Add(new Warning(severity.ToString(), message, report));
        }
예제 #7
0
        private static void WriteValidationMessages(CompetitionState competitionState)
        {
            if (competitionState.LastRunSummary == null)
            {
                return;
            }

            foreach (var validationError in competitionState.LastRunSummary.ValidationErrors)
            {
                var severity = validationError.IsCritical ? MessageSeverity.SetupError : MessageSeverity.Warning;
                var message  = validationError.Benchmark == null
                                        ? validationError.Message
                                        : $"Benchmark {validationError.Benchmark.ShortInfo}:{Environment.NewLine}\t{validationError.Message}";

                competitionState.WriteMessage(MessageSource.Validator, severity, message);
            }
        }
예제 #8
0
        private static void RunCore(Type benchmarkType, CompetitionState competitionState)
        {
            var logger     = competitionState.Logger;
            var runOptions = competitionState.Options.RunOptions;

            Code.InRange(
                runOptions.MaxRunsAllowed,
                CompetitionRunMode.MaxRunsAllowedCharacteristic.FullId,
                0, MaxRunLimit);

            while (competitionState.RunsLeft > 0)
            {
                competitionState.PrepareForRun();

                var run          = competitionState.RunNumber;
                var runsExpected = competitionState.RunNumber + competitionState.RunsLeft;
                var runMessage   = competitionState.RunLimitExceeded
                                        ? $"Run {run}, total runs (expected): {runsExpected} (rerun limit exceeded, last run)"
                                        : $"Run {run}, total runs (expected): {runsExpected}";

                using (BeginLogImportant(competitionState.Config))
                {
                    logger.WriteSeparatorLine(runMessage);
                }

                // TODO: toolchainProvider to base (???).
                Func <Job, IToolchain> toolchainProvider = j => j.Infrastructure?.Toolchain ?? InProcessToolchain.Instance;

                // Running the benchmark
                var summary = BenchmarkRunnerCore.Run(
                    BenchmarkConverter.TypeToBenchmarks(benchmarkType, competitionState.Config),
                    competitionState.Config,
                    toolchainProvider);
                competitionState.RunCompleted(summary);

                // Dump messages if analysis was not run and there is a validation analyser.
                if (summary.HasCriticalValidationErrors)
                {
                    var validationAnalyser = competitionState.Config
                                             .GetAnalysers()
                                             .OfType <ValidatorMessagesAnalyser>()
                                             .FirstOrDefault();
                    validationAnalyser?.Analyse(summary);
                }

                if (competitionState.HasCriticalErrorsInRun)
                {
                    competitionState.Logger.WriteVerboseHint("Breaking competition execution. High severity error occured.");
                    break;
                }

                if (competitionState.RunLimitExceeded)
                {
                    break;
                }

                if (competitionState.RunsLeft > 0)
                {
                    competitionState.Logger.WriteVerboseHint($"Rerun requested. Runs left: {competitionState.RunsLeft}.");
                }
            }

            if (competitionState.RunLimitExceeded && competitionState.RunsLeft > 0)
            {
                competitionState.WriteMessage(
                    MessageSource.Runner, MessageSeverity.TestError,
                    $"The benchmark run limit ({runOptions.MaxRunsAllowed} runs(s)) exceeded, check log for details.");
            }
            else if (competitionState.RunNumber > 1)
            {
                competitionState.WriteMessage(
                    MessageSource.Runner, MessageSeverity.Warning,
                    $"The benchmark was run {competitionState.RunNumber} time(s), check log for details.");
            }
        }