diff --git a/samples/BenchmarkDotNet.Samples/IntroExceptionDiagnoser.cs b/samples/BenchmarkDotNet.Samples/IntroExceptionDiagnoser.cs index 7e0f847c95..81f2b79c28 100644 --- a/samples/BenchmarkDotNet.Samples/IntroExceptionDiagnoser.cs +++ b/samples/BenchmarkDotNet.Samples/IntroExceptionDiagnoser.cs @@ -6,20 +6,10 @@ namespace BenchmarkDotNet.Samples [ExceptionDiagnoser] public class IntroExceptionDiagnoser { - [Benchmark] - public void ThrowExceptionRandomly() + [Benchmark] public void NoThrow() { } + [Benchmark] public void Throw() { - try - { - if (new Random().Next(0, 5) > 1) - { - throw new Exception(); - } - } - catch - { - // ignored - } + try { throw new Exception(); } catch { } } } } diff --git a/src/BenchmarkDotNet/Attributes/ExceptionDiagnoserAttribute.cs b/src/BenchmarkDotNet/Attributes/ExceptionDiagnoserAttribute.cs index bff956e968..6dc8ae525b 100644 --- a/src/BenchmarkDotNet/Attributes/ExceptionDiagnoserAttribute.cs +++ b/src/BenchmarkDotNet/Attributes/ExceptionDiagnoserAttribute.cs @@ -9,6 +9,10 @@ public class ExceptionDiagnoserAttribute : Attribute, IConfigSource { public IConfig Config { get; } - public ExceptionDiagnoserAttribute() => Config = ManualConfig.CreateEmpty().AddDiagnoser(ExceptionDiagnoser.Default); + /// Display Exceptions column. True by default. + public ExceptionDiagnoserAttribute(bool displayExceptions = true) + { + Config = ManualConfig.CreateEmpty().AddDiagnoser(new ExceptionDiagnoser(new ExceptionDiagnoserConfig(displayExceptions))); + } } -} +} \ No newline at end of file diff --git a/src/BenchmarkDotNet/Attributes/ThreadingDiagnoserAttribute.cs b/src/BenchmarkDotNet/Attributes/ThreadingDiagnoserAttribute.cs index 7627170b8b..05b841c4dc 100644 --- a/src/BenchmarkDotNet/Attributes/ThreadingDiagnoserAttribute.cs +++ b/src/BenchmarkDotNet/Attributes/ThreadingDiagnoserAttribute.cs @@ -9,6 +9,11 @@ public class ThreadingDiagnoserAttribute : Attribute, IConfigSource { public IConfig Config { get; } - public ThreadingDiagnoserAttribute() => Config = ManualConfig.CreateEmpty().AddDiagnoser(ThreadingDiagnoser.Default); + /// Display Work Items column. True by default. + /// Display Lock Contentions column. True by default. + public ThreadingDiagnoserAttribute(bool displayWorkItemsColumn = true, bool displayLockContentionsColumn = true) + { + Config = ManualConfig.CreateEmpty().AddDiagnoser(new ThreadingDiagnoser(new ThreadingDiagnoserConfig(displayWorkItemsColumn, displayLockContentionsColumn))); + } } } \ No newline at end of file diff --git a/src/BenchmarkDotNet/Diagnosers/ExceptionDiagnoser.cs b/src/BenchmarkDotNet/Diagnosers/ExceptionDiagnoser.cs index 782e895d3e..58e8144904 100644 --- a/src/BenchmarkDotNet/Diagnosers/ExceptionDiagnoser.cs +++ b/src/BenchmarkDotNet/Diagnosers/ExceptionDiagnoser.cs @@ -14,9 +14,11 @@ namespace BenchmarkDotNet.Diagnosers { public class ExceptionDiagnoser : IDiagnoser { - public static readonly ExceptionDiagnoser Default = new ExceptionDiagnoser(); + public static readonly ExceptionDiagnoser Default = new ExceptionDiagnoser(new ExceptionDiagnoserConfig(true)); - private ExceptionDiagnoser() { } + public ExceptionDiagnoser(ExceptionDiagnoserConfig config) => Config = config; + + public ExceptionDiagnoserConfig Config { get; } public IEnumerable Ids => new[] { nameof(ExceptionDiagnoser) }; @@ -32,7 +34,10 @@ public void Handle(HostSignal signal, DiagnoserActionParameters parameters) { } public IEnumerable ProcessResults(DiagnoserResults results) { - yield return new Metric(ExceptionsFrequencyMetricDescriptor.Instance, results.ExceptionFrequency); + if (Config.DisplayExceptionsIfZeroValue || results.ExceptionFrequency != 0) + { + yield return new Metric(ExceptionsFrequencyMetricDescriptor.Instance, results.ExceptionFrequency); + } } public IEnumerable Validate(ValidationParameters validationParameters) => Enumerable.Empty(); diff --git a/src/BenchmarkDotNet/Diagnosers/ExceptionDiagnoserConfig.cs b/src/BenchmarkDotNet/Diagnosers/ExceptionDiagnoserConfig.cs new file mode 100644 index 0000000000..0ebfd06c4e --- /dev/null +++ b/src/BenchmarkDotNet/Diagnosers/ExceptionDiagnoserConfig.cs @@ -0,0 +1,15 @@ +using JetBrains.Annotations; + +namespace BenchmarkDotNet.Diagnosers; + +public class ExceptionDiagnoserConfig +{ + /// Display Exceptions column if it's value is not calculated. True by default. + [PublicAPI] + public ExceptionDiagnoserConfig(bool displayExceptionsIfZeroValue = true) + { + DisplayExceptionsIfZeroValue = displayExceptionsIfZeroValue; + } + + public bool DisplayExceptionsIfZeroValue { get; } +} \ No newline at end of file diff --git a/src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoser.cs b/src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoser.cs index dd2a60efca..0a74d2487d 100644 --- a/src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoser.cs +++ b/src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoser.cs @@ -15,9 +15,11 @@ namespace BenchmarkDotNet.Diagnosers { public class ThreadingDiagnoser : IDiagnoser { - public static readonly ThreadingDiagnoser Default = new ThreadingDiagnoser(); + public static readonly ThreadingDiagnoser Default = new ThreadingDiagnoser(new ThreadingDiagnoserConfig(true, true)); - private ThreadingDiagnoser() { } + public ThreadingDiagnoser(ThreadingDiagnoserConfig config) => Config = config; + + public ThreadingDiagnoserConfig Config { get; } public IEnumerable Ids => new[] { nameof(ThreadingDiagnoser) }; @@ -33,8 +35,15 @@ public void Handle(HostSignal signal, DiagnoserActionParameters parameters) { } public IEnumerable ProcessResults(DiagnoserResults results) { - yield return new Metric(CompletedWorkItemCountMetricDescriptor.Instance, results.ThreadingStats.CompletedWorkItemCount / (double)results.ThreadingStats.TotalOperations); - yield return new Metric(LockContentionCountMetricDescriptor.Instance, results.ThreadingStats.LockContentionCount / (double)results.ThreadingStats.TotalOperations); + if (Config.DisplayWorkItemsColumnIfZeroValue || results.ThreadingStats.CompletedWorkItemCount != 0) + { + yield return new Metric(CompletedWorkItemCountMetricDescriptor.Instance, results.ThreadingStats.CompletedWorkItemCount / (double)results.ThreadingStats.TotalOperations); + } + + if (Config.DisplayLockContentionsColumnIfZeroValue || results.ThreadingStats.LockContentionCount != 0) + { + yield return new Metric(LockContentionCountMetricDescriptor.Instance, results.ThreadingStats.LockContentionCount / (double)results.ThreadingStats.TotalOperations); + } } public IEnumerable Validate(ValidationParameters validationParameters) diff --git a/src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoserConfig.cs b/src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoserConfig.cs new file mode 100644 index 0000000000..eed486c774 --- /dev/null +++ b/src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoserConfig.cs @@ -0,0 +1,18 @@ +using JetBrains.Annotations; + +namespace BenchmarkDotNet.Diagnosers; + +public class ThreadingDiagnoserConfig +{ + /// Display Work Items column if it's value is not calculated. True by default. + /// Display Lock Contentions column if it's value is not calculated. True by default. + [PublicAPI] + public ThreadingDiagnoserConfig(bool displayWorkItemsColumnIfZeroValue = true, bool displayLockContentionsColumnIfZeroValue = true) + { + DisplayWorkItemsColumnIfZeroValue = displayWorkItemsColumnIfZeroValue; + DisplayLockContentionsColumnIfZeroValue = displayLockContentionsColumnIfZeroValue; + } + public bool DisplayWorkItemsColumnIfZeroValue { get; } + + public bool DisplayLockContentionsColumnIfZeroValue { get; } +} \ No newline at end of file diff --git a/tests/BenchmarkDotNet.IntegrationTests/ExceptionDiagnoserTests.cs b/tests/BenchmarkDotNet.IntegrationTests/ExceptionDiagnoserTests.cs index 71e4ba29bb..334a434db2 100644 --- a/tests/BenchmarkDotNet.IntegrationTests/ExceptionDiagnoserTests.cs +++ b/tests/BenchmarkDotNet.IntegrationTests/ExceptionDiagnoserTests.cs @@ -30,6 +30,14 @@ public void ExceptionCountIsAccurate() }); } + [Fact] + public void ExceptionTest() + { + var config = CreateConfig(); + + var summary = BenchmarkRunner.Run(config); + } + public class ExceptionCount { [Benchmark] @@ -45,6 +53,19 @@ public void ThrowOneException() [Benchmark] public void DoNothing() { } + [Benchmark] + public void NoThrow() { } + + [Benchmark] + public void Throw() + { + try + { + throw new Exception(); + } + catch { } + } + [Benchmark] public async Task ThrowFromMultipleThreads() {