Skip to content

Commit cac4f6e

Browse files
authored
Feature Request: Add ability to automatically hide metric columns if value is not set (#2673)
* Hide the columns described in the issue & add samples for test * Polish sample names * remove irrelevant commit from pr * remove leftovers * Added some helper classes to inject the configuration into the descriptor handler. Added attribute parameters instead of checking the metric.Value directly. * change the injection of configuration * add tests * return the singleton pattern * change private descriptors into internal Implement descriptorConfigInjector base class to keep the code dry * remove DescriptorConfigInjector * remove samples
1 parent cd50f7b commit cac4f6e

File tree

7 files changed

+421
-17
lines changed

7 files changed

+421
-17
lines changed

src/BenchmarkDotNet/Attributes/ExceptionDiagnoserAttribute.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ public class ExceptionDiagnoserAttribute : Attribute, IConfigSource
99
{
1010
public IConfig Config { get; }
1111

12-
public ExceptionDiagnoserAttribute() => Config = ManualConfig.CreateEmpty().AddDiagnoser(ExceptionDiagnoser.Default);
12+
/// <param name="displayExceptionsIfZeroValue">Display Exceptions column. True by default.</param>
13+
public ExceptionDiagnoserAttribute(bool displayExceptionsIfZeroValue = true)
14+
{
15+
Config = ManualConfig.CreateEmpty().AddDiagnoser(new ExceptionDiagnoser(new ExceptionDiagnoserConfig(displayExceptionsIfZeroValue)));
16+
}
1317
}
1418
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using JetBrains.Annotations;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Text;
5+
6+
namespace BenchmarkDotNet.Attributes
7+
{
8+
public class ExceptionDiagnoserConfig
9+
{
10+
/// <param name="displayExceptionsIfZeroValue">Determines whether the Exceptions column is displayed when its value is not calculated. True by default.</param>
11+
12+
[PublicAPI]
13+
public ExceptionDiagnoserConfig(bool displayExceptionsIfZeroValue = true)
14+
{
15+
DisplayExceptionsIfZeroValue = displayExceptionsIfZeroValue;
16+
}
17+
18+
public bool DisplayExceptionsIfZeroValue { get; }
19+
}
20+
}
Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using BenchmarkDotNet.Configs;
33
using BenchmarkDotNet.Diagnosers;
4+
using JetBrains.Annotations;
45

56
namespace BenchmarkDotNet.Attributes
67
{
@@ -9,6 +10,15 @@ public class ThreadingDiagnoserAttribute : Attribute, IConfigSource
910
{
1011
public IConfig Config { get; }
1112

12-
public ThreadingDiagnoserAttribute() => Config = ManualConfig.CreateEmpty().AddDiagnoser(ThreadingDiagnoser.Default);
13+
//public ThreadingDiagnoserAttribute() => Config = ManualConfig.CreateEmpty().AddDiagnoser(ThreadingDiagnoser.Default);
14+
15+
/// <param name="displayLockContentionWhenZero">Display configuration for 'LockContentionCount' when it is empty. True (displayed) by default.</param>
16+
/// <param name="displayCompletedWorkItemCountWhenZero">Display configuration for 'CompletedWorkItemCount' when it is empty. True (displayed) by default.</param>
17+
18+
[PublicAPI]
19+
public ThreadingDiagnoserAttribute(bool displayLockContentionWhenZero = true, bool displayCompletedWorkItemCountWhenZero = true)
20+
{
21+
Config = ManualConfig.CreateEmpty().AddDiagnoser(new ThreadingDiagnoser(new ThreadingDiagnoserConfig(displayLockContentionWhenZero, displayCompletedWorkItemCountWhenZero)));
22+
}
1323
}
1424
}

src/BenchmarkDotNet/Diagnosers/ExceptionDiagnoser.cs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using BenchmarkDotNet.Analysers;
2+
using BenchmarkDotNet.Attributes;
23
using BenchmarkDotNet.Columns;
34
using BenchmarkDotNet.Engines;
45
using BenchmarkDotNet.Exporters;
@@ -14,9 +15,11 @@ namespace BenchmarkDotNet.Diagnosers
1415
{
1516
public class ExceptionDiagnoser : IDiagnoser
1617
{
17-
public static readonly ExceptionDiagnoser Default = new ExceptionDiagnoser();
18+
public static readonly ExceptionDiagnoser Default = new ExceptionDiagnoser(new ExceptionDiagnoserConfig(displayExceptionsIfZeroValue: true));
1819

19-
private ExceptionDiagnoser() { }
20+
public ExceptionDiagnoser(ExceptionDiagnoserConfig config) => Config = config;
21+
22+
public ExceptionDiagnoserConfig Config { get; }
2023

2124
public IEnumerable<string> Ids => new[] { nameof(ExceptionDiagnoser) };
2225

@@ -32,14 +35,18 @@ public void Handle(HostSignal signal, DiagnoserActionParameters parameters) { }
3235

3336
public IEnumerable<Metric> ProcessResults(DiagnoserResults results)
3437
{
35-
yield return new Metric(ExceptionsFrequencyMetricDescriptor.Instance, results.ExceptionFrequency);
38+
yield return new Metric(new ExceptionsFrequencyMetricDescriptor(Config), results.ExceptionFrequency);
3639
}
3740

3841
public IEnumerable<ValidationError> Validate(ValidationParameters validationParameters) => Enumerable.Empty<ValidationError>();
3942

40-
private class ExceptionsFrequencyMetricDescriptor : IMetricDescriptor
43+
internal class ExceptionsFrequencyMetricDescriptor : IMetricDescriptor
4144
{
42-
internal static readonly IMetricDescriptor Instance = new ExceptionsFrequencyMetricDescriptor();
45+
public ExceptionDiagnoserConfig Config { get; }
46+
public ExceptionsFrequencyMetricDescriptor(ExceptionDiagnoserConfig config = null)
47+
{
48+
Config = config;
49+
}
4350

4451
public string Id => "ExceptionFrequency";
4552
public string DisplayName => Column.Exceptions;
@@ -49,7 +56,13 @@ private class ExceptionsFrequencyMetricDescriptor : IMetricDescriptor
4956
public string Unit => "Count";
5057
public bool TheGreaterTheBetter => false;
5158
public int PriorityInCategory => 0;
52-
public bool GetIsAvailable(Metric metric) => true;
59+
public bool GetIsAvailable(Metric metric)
60+
{
61+
if (Config == null)
62+
return metric.Value > 0;
63+
else
64+
return Config.DisplayExceptionsIfZeroValue || metric.Value > 0;
65+
}
5366
}
5467
}
55-
}
68+
}

src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoser.cs

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ namespace BenchmarkDotNet.Diagnosers
1515
{
1616
public class ThreadingDiagnoser : IDiagnoser
1717
{
18-
public static readonly ThreadingDiagnoser Default = new ThreadingDiagnoser();
18+
public static readonly ThreadingDiagnoser Default = new ThreadingDiagnoser(new ThreadingDiagnoserConfig(displayCompletedWorkItemCountWhenZero: true, displayLockContentionWhenZero: true));
1919

20-
private ThreadingDiagnoser() { }
20+
public ThreadingDiagnoser(ThreadingDiagnoserConfig config) => Config = config;
21+
public ThreadingDiagnoserConfig Config { get; }
2122

2223
public IEnumerable<string> Ids => new[] { nameof(ThreadingDiagnoser) };
2324

@@ -33,8 +34,9 @@ public void Handle(HostSignal signal, DiagnoserActionParameters parameters) { }
3334

3435
public IEnumerable<Metric> ProcessResults(DiagnoserResults results)
3536
{
36-
yield return new Metric(CompletedWorkItemCountMetricDescriptor.Instance, results.ThreadingStats.CompletedWorkItemCount / (double)results.ThreadingStats.TotalOperations);
37-
yield return new Metric(LockContentionCountMetricDescriptor.Instance, results.ThreadingStats.LockContentionCount / (double)results.ThreadingStats.TotalOperations);
37+
38+
yield return new Metric(new CompletedWorkItemCountMetricDescriptor(Config), results.ThreadingStats.CompletedWorkItemCount / (double)results.ThreadingStats.TotalOperations);
39+
yield return new Metric(new LockContentionCountMetricDescriptor(Config), results.ThreadingStats.LockContentionCount / (double)results.ThreadingStats.TotalOperations);
3840
}
3941

4042
public IEnumerable<ValidationError> Validate(ValidationParameters validationParameters)
@@ -50,10 +52,15 @@ public IEnumerable<ValidationError> Validate(ValidationParameters validationPara
5052
}
5153
}
5254

53-
private class CompletedWorkItemCountMetricDescriptor : IMetricDescriptor
55+
internal class CompletedWorkItemCountMetricDescriptor : IMetricDescriptor
5456
{
5557
internal static readonly IMetricDescriptor Instance = new CompletedWorkItemCountMetricDescriptor();
5658

59+
private ThreadingDiagnoserConfig Config { get; }
60+
public CompletedWorkItemCountMetricDescriptor(ThreadingDiagnoserConfig config = null)
61+
{
62+
Config = config;
63+
}
5764
public string Id => "CompletedWorkItemCount";
5865
public string DisplayName => Column.CompletedWorkItems;
5966
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
6269
public string Unit => "Count";
6370
public bool TheGreaterTheBetter => false;
6471
public int PriorityInCategory => 0;
65-
public bool GetIsAvailable(Metric metric) => true;
72+
public bool GetIsAvailable(Metric metric)
73+
{
74+
if (Config == null)
75+
return metric.Value > 0;
76+
else
77+
return Config.DisplayCompletedWorkItemCountWhenZero || metric.Value > 0;
78+
}
6679
}
6780

68-
private class LockContentionCountMetricDescriptor : IMetricDescriptor
81+
internal class LockContentionCountMetricDescriptor : IMetricDescriptor
6982
{
7083
internal static readonly IMetricDescriptor Instance = new LockContentionCountMetricDescriptor();
7184

85+
private ThreadingDiagnoserConfig Config { get; }
86+
87+
public LockContentionCountMetricDescriptor(ThreadingDiagnoserConfig config = null)
88+
{
89+
Config = config;
90+
}
91+
7292
public string Id => "LockContentionCount";
7393
public string DisplayName => Column.LockContentions;
7494
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
7797
public string Unit => "Count";
7898
public bool TheGreaterTheBetter => false;
7999
public int PriorityInCategory => 0;
80-
public bool GetIsAvailable(Metric metric) => true;
100+
public bool GetIsAvailable(Metric metric)
101+
{
102+
if (Config == null)
103+
return metric.Value > 0;
104+
else
105+
return Config.DisplayLockContentionWhenZero || metric.Value > 0;
106+
}
81107
}
82108
}
83109
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using JetBrains.Annotations;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Text;
5+
6+
namespace BenchmarkDotNet.Diagnosers
7+
{
8+
public class ThreadingDiagnoserConfig
9+
{
10+
/// <param name="displayLockContentionWhenZero">Display configuration for 'LockContentionCount' when it is empty. True (displayed) by default.</param>
11+
/// <param name="displayCompletedWorkItemCountWhenZero">Display configuration for 'CompletedWorkItemCount' when it is empty. True (displayed) by default.</param>
12+
13+
[PublicAPI]
14+
public ThreadingDiagnoserConfig(bool displayLockContentionWhenZero = true, bool displayCompletedWorkItemCountWhenZero = true)
15+
{
16+
DisplayLockContentionWhenZero = displayLockContentionWhenZero;
17+
DisplayCompletedWorkItemCountWhenZero = displayCompletedWorkItemCountWhenZero;
18+
}
19+
20+
public bool DisplayLockContentionWhenZero { get; }
21+
public bool DisplayCompletedWorkItemCountWhenZero { get; }
22+
}
23+
}

0 commit comments

Comments
 (0)