private static bool SpinWait( Mutex mutex, TimeSpan waitTimeout, TimeSpan spinWaitTimeout, IMessageLogger messageLogger) { Code.InRange(waitTimeout, nameof(spinWaitTimeout), TimeSpan.Zero, _totalWaitTimeout); Code.InRange(spinWaitTimeout, nameof(spinWaitTimeout), TimeSpan.Zero, _totalWaitTimeout); if (spinWaitTimeout > waitTimeout) { spinWaitTimeout = waitTimeout; } bool lockTaken = false; var totalSpinTime = TimeSpan.Zero; while (!lockTaken && totalSpinTime < waitTimeout) { try { lockTaken = mutex.WaitOne(spinWaitTimeout); if (!lockTaken) { messageLogger.WriteInfoMessage($"Another perftest is running, wait timeout {totalSpinTime} of {waitTimeout}."); } else if (totalSpinTime > TimeSpan.Zero) { messageLogger.WriteInfoMessage( $"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. messageLogger.WriteExceptionMessage( MessageSeverity.Informational, $"Another perftest aborted, starting. Wait timeout {totalSpinTime} of {waitTimeout}.", ex); lockTaken = true; } totalSpinTime += spinWaitTimeout; } return(lockTaken); }
private static StoredTargetInfo TryGetStoredTarget( Target target, MetricInfo[] metrics, IMessageLogger messageLogger) { var metricsByType = metrics.ToDictionary(m => m.AttributeType); var result = new List <StoredMetricValue>(metricsByType.Count); foreach (var metricAttribute in target.Method.GetMetadataAttributes <IStoredMetricValue>(true).ToArray()) { if (!metricsByType.ContainsKey(metricAttribute.MetricAttributeType)) { // TODO: improve check for primary metric? if (metricAttribute.MetricAttributeType != MetricInfo.PrimaryMetric.AttributeType) { // TODO: common API for unknown metrics, refactor it to base? var metricName = metricAttribute.MetricAttributeType.GetShortAttributeName(); messageLogger.WriteInfoMessage( target, $"Metric {metricName} not listed in config and therefore is ignored.", $"List of metrics is exposed as {nameof(ICompetitionConfig)}.{nameof(ICompetitionConfig.GetMetrics)}()."); } continue; } // Transport object allows to not hold ref to the attribute. var storedMetric = new StoredMetricValue( metricAttribute.MetricAttributeType, metricAttribute.Min, metricAttribute.Max, metricAttribute.UnitOfMeasurement); result.Add(storedMetric); } return(new StoredTargetInfo(result.ToArray())); }
private static StoredTargetInfo TryGetStoredTarget( Target target, MetricInfo[] metrics, IMessageLogger messageLogger) { var metricsByType = metrics.ToDictionary(m => m.AttributeType); var result = new List <StoredMetricValue>(metricsByType.Count); foreach (var metricAttribute in target.Method.GetMetadataAttributes <IStoredMetricValue>(true).ToArray()) { if (!metricsByType.ContainsKey(metricAttribute.MetricAttributeType)) { // TODO: improve check for primary metric? if (metricAttribute.MetricAttributeType != MetricInfo.PrimaryMetric.AttributeType) { // TODO: common API for unknown metrics, refactor it to base? messageLogger.WriteInfoMessage( target, $"unknown metric {metricAttribute.MetricAttributeType.Name}, ignored."); } continue; } // Transport object used to not hold ref to the attribute. var storedMetric = new StoredMetricValue( metricAttribute.MetricAttributeType, metricAttribute.Min, metricAttribute.Max, metricAttribute.UnitOfMeasurement); result.Add(storedMetric); } return(new StoredTargetInfo(result.ToArray())); }
protected static CompetitionTarget ParseCompetitionTarget( [NotNull] Target target, [NotNull] MetricInfo[] metrics, [CanBeNull] StoredTargetInfo storedTarget, [NotNull] IMessageLogger messageLogger) { if (storedTarget == null) { messageLogger.WriteInfoMessage( target, "Has no annotations applied, all metrics will be treated as empty.", "Check if the method was renamed; add annotations for the method or enable auto-annotation feature."); return(CreateEmptyCompetitionTarget(target, metrics)); } if (storedTarget.Baseline != null && storedTarget.Baseline != target.Baseline) { messageLogger.WriteSetupErrorMessage( target, "Baseline flag on the method and in the annotation do not match.", "Check if the method was renamed. Rename it back or update previous run log with new method name."); } var parseEvents = new List <(MetricInfo metric, MetricParseEvent parseEvent)>(); var result = ParseCompetitionMetricValues(target, metrics, storedTarget, parseEvents); ReportParseEventSummary(target, parseEvents, messageLogger); return(new CompetitionTarget(target, result.ToArray())); }
private static bool CheckCompetitionAttribute(Target target, IMessageLogger messageLogger) { var benchmarkAttribute = target.Method.GetCustomAttribute <CompetitionBenchmarkAttribute>(false); if (benchmarkAttribute == null) { messageLogger.WriteInfoMessage( target, $"Metric validation skipped as the method is not marked with {nameof(CompetitionBenchmarkAttribute)}."); return(false); } if (benchmarkAttribute.DoesNotCompete) { messageLogger.WriteInfoMessage( target, "Metric validation skipped as the method is marked with " + $"{nameof(CompetitionBenchmarkAttribute)}.{nameof(CompetitionBenchmarkAttribute.DoesNotCompete)} set to true."); return(false); } return(true); }
private static bool CheckPreconditions( CompetitionState competitionState, bool lockTaken, IMessageLogger messageLogger) { var runOptions = competitionState.Options.RunOptions; if (!lockTaken) { switch (runOptions.Concurrent) { case ConcurrentRunBehavior.Lock: case ConcurrentRunBehavior.Skip: messageLogger.WriteWarningMessage( "Competition run skipped. Competitions cannot be run in parallel, be sure to disable parallel test execution."); return(false); case ConcurrentRunBehavior.Fail: messageLogger.WriteSetupErrorMessage( "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); } } var benchmarkAssembly = competitionState.BenchmarkType.Assembly; if (!runOptions.AllowDebugBuilds && benchmarkAssembly.IsDebugAssembly()) { messageLogger.WriteWarningMessage( $"Competition run skipped. Assembly {benchmarkAssembly.GetName().Name} was build as debug."); return(false); } if (runOptions.ContinuousIntegrationMode) { messageLogger.WriteInfoMessage( "Competition is run under continuous integration service."); } return(true); }
protected static CompetitionTarget ParseCompetitionTarget( [NotNull] Target target, [NotNull] MetricInfo[] metrics, [CanBeNull] StoredTargetInfo storedTarget, [NotNull] IMessageLogger messageLogger) { var result = new List <CompetitionMetricValue>(); if (storedTarget == null) { messageLogger.WriteInfoMessage( target, "Has no annotations applied, all metrics will be threated as empty.", "Check if the method was renamed; add annnotations for the method or enable auto-annotation feature."); return(new CompetitionTarget(target, result.ToArray())); } if (storedTarget.Baseline != null && storedTarget.Baseline != target.Baseline) { messageLogger.WriteSetupErrorMessage( target, "Baseline flag on the method and in the annotation do not match.", "Check if the method was renamed. Rename it back or update previous run log with new method name."); } var hasAnyMetric = storedTarget.MetricValues.Any(); // TODO: group messages into one? var metricsByType = storedTarget.MetricValues.ToDictionary(m => m.MetricAttributeType); foreach (var metric in metrics) { var metricIsApplicable = !target.Baseline || !metric.IsRelative; if (metricsByType.TryGetValue(metric.AttributeType, out var storedMetric)) { if (metricIsApplicable) { var metricValue = storedMetric.ToMetricValue(metric); if (CheckMetricValue(target, metricValue, messageLogger)) { result.Add(storedMetric.ToMetricValue(metric)); } } else if (!metric.IsPrimaryMetric) { messageLogger.WriteSetupErrorMessage( target, $"Annotation for relative metric {metric} cannot be applied as the target is baseline.", "Check if baseline method for the competition was changed."); } } else if (metricIsApplicable) { if (hasAnyMetric) { messageLogger.WriteInfoMessage( target, $"Annotation for metric {metric} not found, threated as empty.", "Add annnotation for the metric or enable auto-annotation feature."); } result.Add(new CompetitionMetricValue(metric)); } } return(new CompetitionTarget(target, result.ToArray())); }