diff --git a/src/BenchmarkDotNet/Attributes/ExceptionDiagnoserAttribute.cs b/src/BenchmarkDotNet/Attributes/ExceptionDiagnoserAttribute.cs
index bff956e968..21f2903124 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 displayExceptionsIfZeroValue = true)
+ {
+ Config = ManualConfig.CreateEmpty().AddDiagnoser(new ExceptionDiagnoser(new ExceptionDiagnoserConfig(displayExceptionsIfZeroValue)));
+ }
}
}
diff --git a/src/BenchmarkDotNet/Attributes/ExceptionDiagnoserConfig.cs b/src/BenchmarkDotNet/Attributes/ExceptionDiagnoserConfig.cs
new file mode 100644
index 0000000000..86f8d99be4
--- /dev/null
+++ b/src/BenchmarkDotNet/Attributes/ExceptionDiagnoserConfig.cs
@@ -0,0 +1,20 @@
+using JetBrains.Annotations;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BenchmarkDotNet.Attributes
+{
+ public class ExceptionDiagnoserConfig
+ {
+ /// Determines whether the Exceptions column is displayed when its value is not calculated. True by default.
+
+ [PublicAPI]
+ public ExceptionDiagnoserConfig(bool displayExceptionsIfZeroValue = true)
+ {
+ DisplayExceptionsIfZeroValue = displayExceptionsIfZeroValue;
+ }
+
+ public bool DisplayExceptionsIfZeroValue { get; }
+ }
+}
diff --git a/src/BenchmarkDotNet/Attributes/ThreadingDiagnoserAttribute.cs b/src/BenchmarkDotNet/Attributes/ThreadingDiagnoserAttribute.cs
index 7627170b8b..4ad7651bfc 100644
--- a/src/BenchmarkDotNet/Attributes/ThreadingDiagnoserAttribute.cs
+++ b/src/BenchmarkDotNet/Attributes/ThreadingDiagnoserAttribute.cs
@@ -1,6 +1,7 @@
using System;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnosers;
+using JetBrains.Annotations;
namespace BenchmarkDotNet.Attributes
{
@@ -9,6 +10,15 @@ public class ThreadingDiagnoserAttribute : Attribute, IConfigSource
{
public IConfig Config { get; }
- public ThreadingDiagnoserAttribute() => Config = ManualConfig.CreateEmpty().AddDiagnoser(ThreadingDiagnoser.Default);
+ //public ThreadingDiagnoserAttribute() => Config = ManualConfig.CreateEmpty().AddDiagnoser(ThreadingDiagnoser.Default);
+
+ /// Display configuration for 'LockContentionCount' when it is empty. True (displayed) by default.
+ /// Display configuration for 'CompletedWorkItemCount' when it is empty. True (displayed) by default.
+
+ [PublicAPI]
+ public ThreadingDiagnoserAttribute(bool displayLockContentionWhenZero = true, bool displayCompletedWorkItemCountWhenZero = true)
+ {
+ Config = ManualConfig.CreateEmpty().AddDiagnoser(new ThreadingDiagnoser(new ThreadingDiagnoserConfig(displayLockContentionWhenZero, displayCompletedWorkItemCountWhenZero)));
+ }
}
}
\ No newline at end of file
diff --git a/src/BenchmarkDotNet/Diagnosers/ExceptionDiagnoser.cs b/src/BenchmarkDotNet/Diagnosers/ExceptionDiagnoser.cs
index 782e895d3e..574d1e54f1 100644
--- a/src/BenchmarkDotNet/Diagnosers/ExceptionDiagnoser.cs
+++ b/src/BenchmarkDotNet/Diagnosers/ExceptionDiagnoser.cs
@@ -1,4 +1,5 @@
using BenchmarkDotNet.Analysers;
+using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Engines;
using BenchmarkDotNet.Exporters;
@@ -14,9 +15,11 @@ namespace BenchmarkDotNet.Diagnosers
{
public class ExceptionDiagnoser : IDiagnoser
{
- public static readonly ExceptionDiagnoser Default = new ExceptionDiagnoser();
+ public static readonly ExceptionDiagnoser Default = new ExceptionDiagnoser(new ExceptionDiagnoserConfig(displayExceptionsIfZeroValue: true));
- private ExceptionDiagnoser() { }
+ public ExceptionDiagnoser(ExceptionDiagnoserConfig config) => Config = config;
+
+ public ExceptionDiagnoserConfig Config { get; }
public IEnumerable Ids => new[] { nameof(ExceptionDiagnoser) };
@@ -32,14 +35,18 @@ public void Handle(HostSignal signal, DiagnoserActionParameters parameters) { }
public IEnumerable ProcessResults(DiagnoserResults results)
{
- yield return new Metric(ExceptionsFrequencyMetricDescriptor.Instance, results.ExceptionFrequency);
+ yield return new Metric(new ExceptionsFrequencyMetricDescriptor(Config), results.ExceptionFrequency);
}
public IEnumerable Validate(ValidationParameters validationParameters) => Enumerable.Empty();
- private class ExceptionsFrequencyMetricDescriptor : IMetricDescriptor
+ internal class ExceptionsFrequencyMetricDescriptor : IMetricDescriptor
{
- internal static readonly IMetricDescriptor Instance = new ExceptionsFrequencyMetricDescriptor();
+ public ExceptionDiagnoserConfig Config { get; }
+ public ExceptionsFrequencyMetricDescriptor(ExceptionDiagnoserConfig config = null)
+ {
+ Config = config;
+ }
public string Id => "ExceptionFrequency";
public string DisplayName => Column.Exceptions;
@@ -49,7 +56,13 @@ private class ExceptionsFrequencyMetricDescriptor : IMetricDescriptor
public string Unit => "Count";
public bool TheGreaterTheBetter => false;
public int PriorityInCategory => 0;
- public bool GetIsAvailable(Metric metric) => true;
+ public bool GetIsAvailable(Metric metric)
+ {
+ if (Config == null)
+ return metric.Value > 0;
+ else
+ return Config.DisplayExceptionsIfZeroValue || metric.Value > 0;
+ }
}
}
-}
+}
\ No newline at end of file
diff --git a/src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoser.cs b/src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoser.cs
index dd2a60efca..52059ca21c 100644
--- a/src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoser.cs
+++ b/src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoser.cs
@@ -15,9 +15,10 @@ namespace BenchmarkDotNet.Diagnosers
{
public class ThreadingDiagnoser : IDiagnoser
{
- public static readonly ThreadingDiagnoser Default = new ThreadingDiagnoser();
+ public static readonly ThreadingDiagnoser Default = new ThreadingDiagnoser(new ThreadingDiagnoserConfig(displayCompletedWorkItemCountWhenZero: true, displayLockContentionWhenZero: true));
- private ThreadingDiagnoser() { }
+ public ThreadingDiagnoser(ThreadingDiagnoserConfig config) => Config = config;
+ public ThreadingDiagnoserConfig Config { get; }
public IEnumerable Ids => new[] { nameof(ThreadingDiagnoser) };
@@ -33,8 +34,9 @@ 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);
+
+ yield return new Metric(new CompletedWorkItemCountMetricDescriptor(Config), results.ThreadingStats.CompletedWorkItemCount / (double)results.ThreadingStats.TotalOperations);
+ yield return new Metric(new LockContentionCountMetricDescriptor(Config), results.ThreadingStats.LockContentionCount / (double)results.ThreadingStats.TotalOperations);
}
public IEnumerable Validate(ValidationParameters validationParameters)
@@ -50,10 +52,15 @@ public IEnumerable Validate(ValidationParameters validationPara
}
}
- private class CompletedWorkItemCountMetricDescriptor : IMetricDescriptor
+ internal class CompletedWorkItemCountMetricDescriptor : IMetricDescriptor
{
internal static readonly IMetricDescriptor Instance = new CompletedWorkItemCountMetricDescriptor();
+ private ThreadingDiagnoserConfig Config { get; }
+ public CompletedWorkItemCountMetricDescriptor(ThreadingDiagnoserConfig config = null)
+ {
+ Config = config;
+ }
public string Id => "CompletedWorkItemCount";
public string DisplayName => Column.CompletedWorkItems;
public string Legend => "The number of work items that have been processed in ThreadPool (per single operation)";
@@ -62,13 +69,26 @@ private class CompletedWorkItemCountMetricDescriptor : IMetricDescriptor
public string Unit => "Count";
public bool TheGreaterTheBetter => false;
public int PriorityInCategory => 0;
- public bool GetIsAvailable(Metric metric) => true;
+ public bool GetIsAvailable(Metric metric)
+ {
+ if (Config == null)
+ return metric.Value > 0;
+ else
+ return Config.DisplayCompletedWorkItemCountWhenZero || metric.Value > 0;
+ }
}
- private class LockContentionCountMetricDescriptor : IMetricDescriptor
+ internal class LockContentionCountMetricDescriptor : IMetricDescriptor
{
internal static readonly IMetricDescriptor Instance = new LockContentionCountMetricDescriptor();
+ private ThreadingDiagnoserConfig Config { get; }
+
+ public LockContentionCountMetricDescriptor(ThreadingDiagnoserConfig config = null)
+ {
+ Config = config;
+ }
+
public string Id => "LockContentionCount";
public string DisplayName => Column.LockContentions;
public string Legend => "The number of times there was contention upon trying to take a Monitor's lock (per single operation)";
@@ -77,7 +97,13 @@ private class LockContentionCountMetricDescriptor : IMetricDescriptor
public string Unit => "Count";
public bool TheGreaterTheBetter => false;
public int PriorityInCategory => 0;
- public bool GetIsAvailable(Metric metric) => true;
+ public bool GetIsAvailable(Metric metric)
+ {
+ if (Config == null)
+ return metric.Value > 0;
+ else
+ return Config.DisplayLockContentionWhenZero || metric.Value > 0;
+ }
}
}
}
\ No newline at end of file
diff --git a/src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoserConfig.cs b/src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoserConfig.cs
new file mode 100644
index 0000000000..6af3da25ac
--- /dev/null
+++ b/src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoserConfig.cs
@@ -0,0 +1,23 @@
+using JetBrains.Annotations;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BenchmarkDotNet.Diagnosers
+{
+ public class ThreadingDiagnoserConfig
+ {
+ /// Display configuration for 'LockContentionCount' when it is empty. True (displayed) by default.
+ /// Display configuration for 'CompletedWorkItemCount' when it is empty. True (displayed) by default.
+
+ [PublicAPI]
+ public ThreadingDiagnoserConfig(bool displayLockContentionWhenZero = true, bool displayCompletedWorkItemCountWhenZero = true)
+ {
+ DisplayLockContentionWhenZero = displayLockContentionWhenZero;
+ DisplayCompletedWorkItemCountWhenZero = displayCompletedWorkItemCountWhenZero;
+ }
+
+ public bool DisplayLockContentionWhenZero { get; }
+ public bool DisplayCompletedWorkItemCountWhenZero { get; }
+ }
+}
diff --git a/tests/BenchmarkDotNet.Tests/Reports/SummaryTableTests.cs b/tests/BenchmarkDotNet.Tests/Reports/SummaryTableTests.cs
index ebea88b5ad..fb15149aa3 100644
--- a/tests/BenchmarkDotNet.Tests/Reports/SummaryTableTests.cs
+++ b/tests/BenchmarkDotNet.Tests/Reports/SummaryTableTests.cs
@@ -1,6 +1,8 @@
using System.Linq;
+using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
+using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Exporters;
using BenchmarkDotNet.Loggers;
using BenchmarkDotNet.Order;
@@ -171,5 +173,311 @@ public void MissingValueInMetricColumnIsNA()
// assert
Assert.Equal(new[] { "-", "NA" }, actual);
}
+
+ #region Issue #2673
+ [Fact]
+ public void DefaultExceptionDiagnoserConfig_WhenExceptionsIsNotZero()
+ {
+
+ // arrange
+ var config = ManualConfig.Create(DefaultConfig.Instance);
+ var exceptionConfig = new ExceptionDiagnoserConfig();
+
+ var exceptionsFrequencyMetricDescriptor = new ExceptionDiagnoser.ExceptionsFrequencyMetricDescriptor(exceptionConfig);
+
+ var metric = new Metric(exceptionsFrequencyMetricDescriptor, 5);
+ var metrics = new[] { metric };
+
+ // act
+ var summary = MockFactory.CreateSummary(config, hugeSd: false, metrics);
+ var table = new SummaryTable(summary);
+ var actual = table.Columns.First(c => c.Header == "Exceptions").Content;
+
+ // assert
+ Assert.Equal(new[] { "5.0000", "5.0000" }, actual);
+ }
+
+ [Fact]
+ public void DefaultExceptionDiagnoserConfig_WhenExceptionsIsZero()
+ {
+
+
+ // arrange
+ var config = ManualConfig.Create(DefaultConfig.Instance);
+ var exceptionConfig = new ExceptionDiagnoserConfig();
+
+ var exceptionsFrequencyMetricDescriptor = new ExceptionDiagnoser.ExceptionsFrequencyMetricDescriptor(exceptionConfig);
+
+ var metric = new Metric(exceptionsFrequencyMetricDescriptor, 0);
+ var metrics = new[] { metric };
+
+ // act
+ var summary = MockFactory.CreateSummary(config, hugeSd: false, metrics);
+ var table = new SummaryTable(summary);
+ var actual = table.Columns.First(c => c.Header == "Exceptions").Content;
+
+ // assert
+ Assert.Equal(new[] { "-", "-" }, actual);
+ }
+
+ [Fact]
+ public void HideExceptionDiagnoserConfig_WhenExceptionsIsNotZero()
+ {
+ // arrange
+ var config = ManualConfig.Create(DefaultConfig.Instance);
+ var exceptionConfig = new ExceptionDiagnoserConfig(displayExceptionsIfZeroValue: false);
+
+ var exceptionsFrequencyMetricDescriptor = new ExceptionDiagnoser.ExceptionsFrequencyMetricDescriptor(exceptionConfig);
+
+ var metric = new Metric(exceptionsFrequencyMetricDescriptor, 5);
+ var metrics = new[] { metric };
+
+ // act
+ var summary = MockFactory.CreateSummary(config, hugeSd: false, metrics);
+ var table = new SummaryTable(summary);
+ var actual = table.Columns.First(c => c.Header == "Exceptions").Content;
+
+ // assert
+ Assert.Equal(new[] { "5.0000", "5.0000" }, actual);
+ }
+
+ [Fact]
+ public void HideExceptionDiagnoserConfig_WhenExceptionsIsZero()
+ {
+
+
+ // arrange
+ var config = ManualConfig.Create(DefaultConfig.Instance);
+ var exceptionConfig = new ExceptionDiagnoserConfig(displayExceptionsIfZeroValue: false);
+
+ var exceptionsFrequencyMetricDescriptor = new ExceptionDiagnoser.ExceptionsFrequencyMetricDescriptor(exceptionConfig);
+
+ var metric = new Metric(exceptionsFrequencyMetricDescriptor, 0);
+ var metrics = new[] { metric };
+
+ // act
+ var summary = MockFactory.CreateSummary(config, hugeSd: false, metrics);
+ var table = new SummaryTable(summary);
+ var isExist = table.Columns.Any(c => c.Header == "Exceptions");
+
+ // assert
+ Assert.False(isExist);
+ }
+
+ [Fact]
+ public void DefaultThreadingDiagnoserConfig_WhenDescriptorValuesAreNotZero()
+ {
+
+ // arrange
+ var config = ManualConfig.Create(DefaultConfig.Instance);
+ var threadingConfig = new ThreadingDiagnoserConfig();
+
+ var lockContentionCountMetricDescriptor = new ThreadingDiagnoser.LockContentionCountMetricDescriptor(threadingConfig);
+ var completedWorkItemCountMetricDescriptor = new ThreadingDiagnoser.CompletedWorkItemCountMetricDescriptor(threadingConfig);
+
+ var lockContentionCountMetric = new Metric(lockContentionCountMetricDescriptor, 5);
+ var completedWorkItemMetric = new Metric(completedWorkItemCountMetricDescriptor, 5);
+ var metrics = new[] { lockContentionCountMetric, completedWorkItemMetric };
+
+ // act
+ var summary = MockFactory.CreateSummary(config, hugeSd: false, metrics);
+ var table = new SummaryTable(summary);
+
+ var lockContentionCount = table.Columns.FirstOrDefault(c => c.Header == "Lock Contentions").Content;
+ var completedWorkItemCount = table.Columns.FirstOrDefault(c => c.Header == "Completed Work Items").Content;
+
+ // assert
+ Assert.Equal(new[] { "5.0000", "5.0000" }, lockContentionCount);
+ Assert.Equal(new[] { "5.0000", "5.0000" }, completedWorkItemCount);
+ }
+
+ [Fact]
+ public void DefaultThreadingDiagnoserConfig_WhenDescriptorValuesAreZero()
+ {
+
+ // arrange
+ var config = ManualConfig.Create(DefaultConfig.Instance);
+ var threadingConfig = new ThreadingDiagnoserConfig();
+
+ var lockContentionCountMetricDescriptor = new ThreadingDiagnoser.LockContentionCountMetricDescriptor(threadingConfig);
+ var completedWorkItemCountMetricDescriptor = new ThreadingDiagnoser.CompletedWorkItemCountMetricDescriptor(threadingConfig);
+
+ var lockContentionCountMetric = new Metric(lockContentionCountMetricDescriptor, 0);
+ var completedWorkItemMetric = new Metric(completedWorkItemCountMetricDescriptor, 0);
+ var metrics = new[] { lockContentionCountMetric, completedWorkItemMetric };
+
+ // act
+ var summary = MockFactory.CreateSummary(config, hugeSd: false, metrics);
+ var table = new SummaryTable(summary);
+
+ var lockContentionCount = table.Columns.FirstOrDefault(c => c.Header == "Lock Contentions").Content;
+ var completedWorkItemCount = table.Columns.FirstOrDefault(c => c.Header == "Completed Work Items").Content;
+
+ // assert
+ Assert.Equal(new[] { "-", "-" }, lockContentionCount);
+ Assert.Equal(new[] { "-", "-" }, completedWorkItemCount);
+ }
+
+ [Fact]
+ public void HideLockContentionCountThreadingDiagnoserConfig_WhenDescriptorValuesAreZero()
+ {
+
+ // arrange
+ var config = ManualConfig.Create(DefaultConfig.Instance);
+ var threadingConfig = new ThreadingDiagnoserConfig(displayLockContentionWhenZero: false);
+
+ var lockContentionCountMetricDescriptor = new ThreadingDiagnoser.LockContentionCountMetricDescriptor(threadingConfig);
+ var completedWorkItemCountMetricDescriptor = new ThreadingDiagnoser.CompletedWorkItemCountMetricDescriptor(threadingConfig);
+
+ var lockContentionCountMetric = new Metric(lockContentionCountMetricDescriptor, 0);
+ var completedWorkItemMetric = new Metric(completedWorkItemCountMetricDescriptor, 0);
+ var metrics = new[] { lockContentionCountMetric, completedWorkItemMetric };
+
+ // act
+ var summary = MockFactory.CreateSummary(config, hugeSd: false, metrics);
+ var table = new SummaryTable(summary);
+
+ string[]? lockContentionCount = table.Columns?.FirstOrDefault(c => c.Header == "Lock Contentions")?.Content ?? null;
+ string[]? completedWorkItemCount = table.Columns?.FirstOrDefault(c => c.Header == "Completed Work Items")?.Content ?? null;
+
+ // assert
+ Assert.Null(lockContentionCount);
+ Assert.Equal(new[] { "-", "-" }, completedWorkItemCount);
+ }
+
+ [Fact]
+ public void HideLockContentionCountThreadingDiagnoserConfig_WhenDescriptorValuesAreNotZero()
+ {
+
+ // arrange
+ var config = ManualConfig.Create(DefaultConfig.Instance);
+ var threadingConfig = new ThreadingDiagnoserConfig(displayLockContentionWhenZero: false);
+
+ var lockContentionCountMetricDescriptor = new ThreadingDiagnoser.LockContentionCountMetricDescriptor(threadingConfig);
+ var completedWorkItemCountMetricDescriptor = new ThreadingDiagnoser.CompletedWorkItemCountMetricDescriptor(threadingConfig);
+
+ var lockContentionCountMetric = new Metric(lockContentionCountMetricDescriptor, 5);
+ var completedWorkItemMetric = new Metric(completedWorkItemCountMetricDescriptor, 5);
+ var metrics = new[] { lockContentionCountMetric, completedWorkItemMetric };
+
+ // act
+ var summary = MockFactory.CreateSummary(config, hugeSd: false, metrics);
+ var table = new SummaryTable(summary);
+
+ string[]? lockContentionCount = table.Columns?.FirstOrDefault(c => c.Header == "Lock Contentions")?.Content ?? null;
+ string[]? completedWorkItemCount = table.Columns?.FirstOrDefault(c => c.Header == "Completed Work Items")?.Content ?? null;
+
+ // assert
+ Assert.Equal(new[] { "5.0000", "5.0000" }, lockContentionCount);
+ Assert.Equal(new[] { "5.0000", "5.0000" }, completedWorkItemCount);
+ }
+
+ [Fact]
+ public void HideCompletedWorkItemCountThreadingDiagnoserConfig_WhenDescriptorValuesAreZero()
+ {
+
+ // arrange
+ var config = ManualConfig.Create(DefaultConfig.Instance);
+ var threadingConfig = new ThreadingDiagnoserConfig(displayCompletedWorkItemCountWhenZero: false);
+
+ var lockContentionCountMetricDescriptor = new ThreadingDiagnoser.LockContentionCountMetricDescriptor(threadingConfig);
+ var completedWorkItemCountMetricDescriptor = new ThreadingDiagnoser.CompletedWorkItemCountMetricDescriptor(threadingConfig);
+
+ var lockContentionCountMetric = new Metric(lockContentionCountMetricDescriptor, 0);
+ var completedWorkItemMetric = new Metric(completedWorkItemCountMetricDescriptor, 0);
+ var metrics = new[] { lockContentionCountMetric, completedWorkItemMetric };
+
+ // act
+ var summary = MockFactory.CreateSummary(config, hugeSd: false, metrics);
+ var table = new SummaryTable(summary);
+
+ string[]? lockContentionCount = table.Columns?.FirstOrDefault(c => c.Header == "Lock Contentions")?.Content ?? null;
+ string[]? completedWorkItemCount = table.Columns?.FirstOrDefault(c => c.Header == "Completed Work Items")?.Content ?? null;
+
+ // assert
+ Assert.Null(completedWorkItemCount);
+ Assert.Equal(new[] { "-", "-" }, lockContentionCount);
+ }
+
+ [Fact]
+ public void HideCompletedWorkItemCountThreadingDiagnoserConfig_WhenDescriptorValuesAreNotZero()
+ {
+
+ // arrange
+ var config = ManualConfig.Create(DefaultConfig.Instance);
+ var threadingConfig = new ThreadingDiagnoserConfig(displayCompletedWorkItemCountWhenZero: false);
+
+ var lockContentionCountMetricDescriptor = new ThreadingDiagnoser.LockContentionCountMetricDescriptor(threadingConfig);
+ var completedWorkItemCountMetricDescriptor = new ThreadingDiagnoser.CompletedWorkItemCountMetricDescriptor(threadingConfig);
+
+ var lockContentionCountMetric = new Metric(lockContentionCountMetricDescriptor, 5);
+ var completedWorkItemMetric = new Metric(completedWorkItemCountMetricDescriptor, 5);
+ var metrics = new[] { lockContentionCountMetric, completedWorkItemMetric };
+
+ // act
+ var summary = MockFactory.CreateSummary(config, hugeSd: false, metrics);
+ var table = new SummaryTable(summary);
+
+ string[]? lockContentionCount = table.Columns?.FirstOrDefault(c => c.Header == "Lock Contentions")?.Content ?? null;
+ string[]? completedWorkItemCount = table.Columns?.FirstOrDefault(c => c.Header == "Completed Work Items")?.Content ?? null;
+
+ // assert
+ Assert.Equal(new[] { "5.0000", "5.0000" }, lockContentionCount);
+ Assert.Equal(new[] { "5.0000", "5.0000" }, completedWorkItemCount);
+ }
+
+ [Fact]
+ public void HideThreadingDiagnoserConfigs_WhenDescriptorValuesAreZero()
+ {
+
+ // arrange
+ var config = ManualConfig.Create(DefaultConfig.Instance);
+ var threadingConfig = new ThreadingDiagnoserConfig(displayCompletedWorkItemCountWhenZero: false, displayLockContentionWhenZero: false);
+
+ var lockContentionCountMetricDescriptor = new ThreadingDiagnoser.LockContentionCountMetricDescriptor(threadingConfig);
+ var completedWorkItemCountMetricDescriptor = new ThreadingDiagnoser.CompletedWorkItemCountMetricDescriptor(threadingConfig);
+
+ var lockContentionCountMetric = new Metric(lockContentionCountMetricDescriptor, 0);
+ var completedWorkItemMetric = new Metric(completedWorkItemCountMetricDescriptor, 0);
+ var metrics = new[] { lockContentionCountMetric, completedWorkItemMetric };
+
+ // act
+ var summary = MockFactory.CreateSummary(config, hugeSd: false, metrics);
+ var table = new SummaryTable(summary);
+
+ string[]? lockContentionCount = table.Columns?.FirstOrDefault(c => c.Header == "Lock Contentions")?.Content ?? null;
+ string[]? completedWorkItemCount = table.Columns?.FirstOrDefault(c => c.Header == "Completed Work Items")?.Content ?? null;
+
+ // assert
+ Assert.Null(lockContentionCount);
+ Assert.Null(completedWorkItemCount);
+ }
+
+ [Fact]
+ public void DisplayThreadingDiagnoserConfigs_WhenDescriptorValuesAreZero()
+ {
+
+ // arrange
+ var config = ManualConfig.Create(DefaultConfig.Instance);
+ var threadingConfig = new ThreadingDiagnoserConfig(displayCompletedWorkItemCountWhenZero: true, displayLockContentionWhenZero: true);
+ var lockContentionCountMetricDescriptor = new ThreadingDiagnoser.LockContentionCountMetricDescriptor(threadingConfig);
+ var completedWorkItemCountMetricDescriptor = new ThreadingDiagnoser.CompletedWorkItemCountMetricDescriptor(threadingConfig);
+
+ var lockContentionCountMetric = new Metric(lockContentionCountMetricDescriptor, 0);
+ var completedWorkItemMetric = new Metric(completedWorkItemCountMetricDescriptor, 0);
+ var metrics = new[] { lockContentionCountMetric, completedWorkItemMetric };
+
+ // act
+ var summary = MockFactory.CreateSummary(config, hugeSd: false, metrics);
+ var table = new SummaryTable(summary);
+
+ string[]? lockContentionCount = table.Columns?.FirstOrDefault(c => c.Header == "Lock Contentions")?.Content ?? null;
+ string[]? completedWorkItemCount = table.Columns?.FirstOrDefault(c => c.Header == "Completed Work Items")?.Content ?? null;
+
+ // assert
+ Assert.Equal(new[] { "-", "-" }, lockContentionCount);
+ Assert.Equal(new[] { "-", "-" }, completedWorkItemCount);
+ }
+ #endregion
}
}
\ No newline at end of file