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); }
// 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); }
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."); } }
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); }
/// <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()); }
/// <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)); }
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); } }
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."); } }