Skip to content

Commit

Permalink
Allow users to hide Gen X columns (#1764)
Browse files Browse the repository at this point in the history
* don't display Gen X collumn if there were no collections for X generation

* add MemoryDiagnoserConfig, allow users to customize MemoryDiagnoser
  • Loading branch information
adamsitnik authored Aug 4, 2021
1 parent 8f81b5b commit f372668
Show file tree
Hide file tree
Showing 12 changed files with 45 additions and 9 deletions.
5 changes: 3 additions & 2 deletions src/BenchmarkDotNet/Attributes/MemoryDiagnoserAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ public class MemoryDiagnoserAttribute : Attribute, IConfigSource
{
public IConfig Config { get; }

public MemoryDiagnoserAttribute()
/// <param name="displayGenColumns">Display Garbage Collections per Generation columns (Gen 0, Gen 1, Gen 2). True by default.</param>
public MemoryDiagnoserAttribute(bool displayGenColumns = true)
{
Config = ManualConfig.CreateEmpty().AddDiagnoser(MemoryDiagnoser.Default);
Config = ManualConfig.CreateEmpty().AddDiagnoser(new MemoryDiagnoser(new MemoryDiagnoserConfig(displayGenColumns)));
}
}
}
2 changes: 1 addition & 1 deletion src/BenchmarkDotNet/Columns/MetricColumn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class MetricColumn : IColumn
public string Legend => descriptor.Legend;
public bool AlwaysShow => true;
public ColumnCategory Category => ColumnCategory.Metric;
public int PriorityInCategory => 0;
public int PriorityInCategory => descriptor.PriorityInCategory;
public bool IsNumeric => true;
public UnitType UnitType => descriptor.UnitType;

Expand Down
2 changes: 1 addition & 1 deletion src/BenchmarkDotNet/Configs/ImmutableConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ internal ImmutableConfig(
public IAnalyser GetCompositeAnalyser() => new CompositeAnalyser(analysers);
public IDiagnoser GetCompositeDiagnoser() => new CompositeDiagnoser(diagnosers);

public bool HasMemoryDiagnoser() => diagnosers.Contains(MemoryDiagnoser.Default);
public bool HasMemoryDiagnoser() => diagnosers.OfType<MemoryDiagnoser>().Any();

public bool HasThreadingDiagnoser() => diagnosers.Contains(ThreadingDiagnoser.Default);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ internal class AllocatedNativeMemoryDescriptor : IMetricDescriptor
public UnitType UnitType => UnitType.Size;
public string Unit => SizeUnit.B.Name;
public bool TheGreaterTheBetter => false;
public int PriorityInCategory => 0;
}

internal class NativeMemoryLeakDescriptor : IMetricDescriptor
Expand All @@ -23,5 +24,6 @@ internal class NativeMemoryLeakDescriptor : IMetricDescriptor
public UnitType UnitType => UnitType.Size;
public string Unit => SizeUnit.B.Name;
public bool TheGreaterTheBetter => false;
public int PriorityInCategory => 0;
}
}
19 changes: 14 additions & 5 deletions src/BenchmarkDotNet/Diagnosers/MemoryDiagnoser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ public class MemoryDiagnoser : IDiagnoser
{
private const string DiagnoserId = nameof(MemoryDiagnoser);

public static readonly MemoryDiagnoser Default = new MemoryDiagnoser();
public static readonly MemoryDiagnoser Default = new MemoryDiagnoser(new MemoryDiagnoserConfig(displayGenColumns: true));

private MemoryDiagnoser() { } // we want to have only a single instance of MemoryDiagnoser
public MemoryDiagnoser(MemoryDiagnoserConfig config) => Config = config;

public MemoryDiagnoserConfig Config { get; }

public RunMode GetRunMode(BenchmarkCase benchmarkCase) => RunMode.NoOverhead;

Expand All @@ -33,9 +35,13 @@ public void Handle(HostSignal signal, DiagnoserActionParameters parameters) { }

public IEnumerable<Metric> ProcessResults(DiagnoserResults diagnoserResults)
{
yield return new Metric(GarbageCollectionsMetricDescriptor.Gen0, diagnoserResults.GcStats.Gen0Collections / (double)diagnoserResults.GcStats.TotalOperations * 1000);
yield return new Metric(GarbageCollectionsMetricDescriptor.Gen1, diagnoserResults.GcStats.Gen1Collections / (double)diagnoserResults.GcStats.TotalOperations * 1000);
yield return new Metric(GarbageCollectionsMetricDescriptor.Gen2, diagnoserResults.GcStats.Gen2Collections / (double)diagnoserResults.GcStats.TotalOperations * 1000);
if (diagnoserResults.GcStats.Gen0Collections > 0 && Config.DisplayGenColumns)
yield return new Metric(GarbageCollectionsMetricDescriptor.Gen0, diagnoserResults.GcStats.Gen0Collections / (double)diagnoserResults.GcStats.TotalOperations * 1000);
if (diagnoserResults.GcStats.Gen1Collections > 0 && Config.DisplayGenColumns)
yield return new Metric(GarbageCollectionsMetricDescriptor.Gen1, diagnoserResults.GcStats.Gen1Collections / (double)diagnoserResults.GcStats.TotalOperations * 1000);
if (diagnoserResults.GcStats.Gen2Collections > 0 && Config.DisplayGenColumns)
yield return new Metric(GarbageCollectionsMetricDescriptor.Gen2, diagnoserResults.GcStats.Gen2Collections / (double)diagnoserResults.GcStats.TotalOperations * 1000);

yield return new Metric(AllocatedMemoryMetricDescriptor.Instance, diagnoserResults.GcStats.GetBytesAllocatedPerOperation(diagnoserResults.BenchmarkCase));
}

Expand All @@ -50,6 +56,7 @@ private class AllocatedMemoryMetricDescriptor : IMetricDescriptor
public UnitType UnitType => UnitType.Size;
public string Unit => SizeUnit.B.Name;
public bool TheGreaterTheBetter => false;
public int PriorityInCategory => GC.MaxGeneration + 1;
}

private class GarbageCollectionsMetricDescriptor : IMetricDescriptor
Expand All @@ -63,6 +70,7 @@ private GarbageCollectionsMetricDescriptor(int generationId)
Id = $"Gen{generationId}Collects";
DisplayName = $"Gen {generationId}";
Legend = $"GC Generation {generationId} collects per 1000 operations";
PriorityInCategory = generationId;
}

public string Id { get; }
Expand All @@ -72,6 +80,7 @@ private GarbageCollectionsMetricDescriptor(int generationId)
public UnitType UnitType => UnitType.Dimensionless;
public string Unit => "Count";
public bool TheGreaterTheBetter => false;
public int PriorityInCategory { get; }
}
}
}
16 changes: 16 additions & 0 deletions src/BenchmarkDotNet/Diagnosers/MemoryDiagnoserConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using JetBrains.Annotations;

namespace BenchmarkDotNet.Diagnosers
{
public class MemoryDiagnoserConfig
{
/// <param name="displayGenColumns">Display Garbage Collections per Generation columns (Gen 0, Gen 1, Gen 2). True by default.</param>
[PublicAPI]
public MemoryDiagnoserConfig(bool displayGenColumns = true)
{
DisplayGenColumns = displayGenColumns;
}

public bool DisplayGenColumns { get; }
}
}
1 change: 1 addition & 0 deletions src/BenchmarkDotNet/Diagnosers/PmcMetricDescriptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ internal PmcMetricDescriptor(PreciseMachineCounter counter)
public string NumberFormat => "N0";
public UnitType UnitType => UnitType.Dimensionless;
public string Unit => "Count";
public int PriorityInCategory => 0;
}
}
2 changes: 2 additions & 0 deletions src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ private class CompletedWorkItemCountMetricDescriptor : IMetricDescriptor
public UnitType UnitType => UnitType.Dimensionless;
public string Unit => "Count";
public bool TheGreaterTheBetter => false;
public int PriorityInCategory => 0;
}

private class LockContentionCountMetricDescriptor : IMetricDescriptor
Expand All @@ -74,6 +75,7 @@ private class LockContentionCountMetricDescriptor : IMetricDescriptor
public UnitType UnitType => UnitType.Dimensionless;
public string Unit => "Count";
public bool TheGreaterTheBetter => false;
public int PriorityInCategory => 0;
}
}
}
1 change: 1 addition & 0 deletions src/BenchmarkDotNet/Disassemblers/DisassemblyDiagnoser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ private class NativeCodeSizeMetricDescriptor : IMetricDescriptor
public UnitType UnitType => UnitType.Size;
public string Unit => SizeUnit.B.Name;
public bool TheGreaterTheBetter => false;
public int PriorityInCategory => 0;
}
}
}
2 changes: 2 additions & 0 deletions src/BenchmarkDotNet/Reports/Metric.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public interface IMetricDescriptor
[PublicAPI] string Unit { get; }

[PublicAPI] bool TheGreaterTheBetter { get; }

[PublicAPI] int PriorityInCategory { get; }
}

public class MetricDescriptorEqualityComparer : EqualityComparer<IMetricDescriptor>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ public FakeMetricDescriptor(string id, string legend, string numberFormat = null
public UnitType UnitType { get; }
public string Unit { get; }
public bool TheGreaterTheBetter { get; }
public int PriorityInCategory => 0;
}
}
1 change: 1 addition & 0 deletions tests/BenchmarkDotNet.Tests/Reports/SummaryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ private sealed class FakeMetricDescriptor : IMetricDescriptor
public UnitType UnitType { get; }
public string Unit { get; } = nameof(Unit);
public bool TheGreaterTheBetter { get; }
public int PriorityInCategory => 0;
}
}
}

0 comments on commit f372668

Please sign in to comment.