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()
{