diff --git a/src/BenchmarkDotNet/Attributes/MemoryDiagnoserAttribute.cs b/src/BenchmarkDotNet/Attributes/MemoryDiagnoserAttribute.cs
index 3cc7b4dcbd..52e2151441 100644
--- a/src/BenchmarkDotNet/Attributes/MemoryDiagnoserAttribute.cs
+++ b/src/BenchmarkDotNet/Attributes/MemoryDiagnoserAttribute.cs
@@ -9,9 +9,10 @@ public class MemoryDiagnoserAttribute : Attribute, IConfigSource
{
public IConfig Config { get; }
- public MemoryDiagnoserAttribute()
+ /// Display Garbage Collections per Generation columns (Gen 0, Gen 1, Gen 2). True by default.
+ public MemoryDiagnoserAttribute(bool displayGenColumns = true)
{
- Config = ManualConfig.CreateEmpty().AddDiagnoser(MemoryDiagnoser.Default);
+ Config = ManualConfig.CreateEmpty().AddDiagnoser(new MemoryDiagnoser(new MemoryDiagnoserConfig(displayGenColumns)));
}
}
}
\ No newline at end of file
diff --git a/src/BenchmarkDotNet/Columns/MetricColumn.cs b/src/BenchmarkDotNet/Columns/MetricColumn.cs
index 1be8241234..56acfebea1 100644
--- a/src/BenchmarkDotNet/Columns/MetricColumn.cs
+++ b/src/BenchmarkDotNet/Columns/MetricColumn.cs
@@ -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;
diff --git a/src/BenchmarkDotNet/Configs/ImmutableConfig.cs b/src/BenchmarkDotNet/Configs/ImmutableConfig.cs
index cc6784c81a..f7ca6df67d 100644
--- a/src/BenchmarkDotNet/Configs/ImmutableConfig.cs
+++ b/src/BenchmarkDotNet/Configs/ImmutableConfig.cs
@@ -92,7 +92,7 @@ public sealed class ImmutableConfig : IConfig
public IAnalyser GetCompositeAnalyser() => new CompositeAnalyser(analysers);
public IDiagnoser GetCompositeDiagnoser() => new CompositeDiagnoser(diagnosers);
- public bool HasMemoryDiagnoser() => diagnosers.Contains(MemoryDiagnoser.Default);
+ public bool HasMemoryDiagnoser() => diagnosers.OfType().Any();
public bool HasThreadingDiagnoser() => diagnosers.Contains(ThreadingDiagnoser.Default);
diff --git a/src/BenchmarkDotNet/Diagnosers/AllocatedNativeMemoryDescriptor.cs b/src/BenchmarkDotNet/Diagnosers/AllocatedNativeMemoryDescriptor.cs
index c0e5ca05be..67e4e2d532 100644
--- a/src/BenchmarkDotNet/Diagnosers/AllocatedNativeMemoryDescriptor.cs
+++ b/src/BenchmarkDotNet/Diagnosers/AllocatedNativeMemoryDescriptor.cs
@@ -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
@@ -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;
}
}
\ No newline at end of file
diff --git a/src/BenchmarkDotNet/Diagnosers/MemoryDiagnoser.cs b/src/BenchmarkDotNet/Diagnosers/MemoryDiagnoser.cs
index e922711b78..8544f81e54 100644
--- a/src/BenchmarkDotNet/Diagnosers/MemoryDiagnoser.cs
+++ b/src/BenchmarkDotNet/Diagnosers/MemoryDiagnoser.cs
@@ -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;
@@ -33,9 +35,13 @@ public class MemoryDiagnoser : IDiagnoser
public IEnumerable 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));
}
@@ -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
@@ -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; }
@@ -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; }
}
}
}
\ No newline at end of file
diff --git a/src/BenchmarkDotNet/Diagnosers/MemoryDiagnoserConfig.cs b/src/BenchmarkDotNet/Diagnosers/MemoryDiagnoserConfig.cs
new file mode 100644
index 0000000000..cb5eb7221e
--- /dev/null
+++ b/src/BenchmarkDotNet/Diagnosers/MemoryDiagnoserConfig.cs
@@ -0,0 +1,16 @@
+using JetBrains.Annotations;
+
+namespace BenchmarkDotNet.Diagnosers
+{
+ public class MemoryDiagnoserConfig
+ {
+ /// Display Garbage Collections per Generation columns (Gen 0, Gen 1, Gen 2). True by default.
+ [PublicAPI]
+ public MemoryDiagnoserConfig(bool displayGenColumns = true)
+ {
+ DisplayGenColumns = displayGenColumns;
+ }
+
+ public bool DisplayGenColumns { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/BenchmarkDotNet/Diagnosers/PmcMetricDescriptor.cs b/src/BenchmarkDotNet/Diagnosers/PmcMetricDescriptor.cs
index f459243072..3e15b5bf87 100644
--- a/src/BenchmarkDotNet/Diagnosers/PmcMetricDescriptor.cs
+++ b/src/BenchmarkDotNet/Diagnosers/PmcMetricDescriptor.cs
@@ -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;
}
}
\ No newline at end of file
diff --git a/src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoser.cs b/src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoser.cs
index d9194dd868..017ddde4b6 100644
--- a/src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoser.cs
+++ b/src/BenchmarkDotNet/Diagnosers/ThreadingDiagnoser.cs
@@ -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
@@ -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;
}
}
}
\ No newline at end of file
diff --git a/src/BenchmarkDotNet/Disassemblers/DisassemblyDiagnoser.cs b/src/BenchmarkDotNet/Disassemblers/DisassemblyDiagnoser.cs
index 2374a7f6bf..541a7fb396 100644
--- a/src/BenchmarkDotNet/Disassemblers/DisassemblyDiagnoser.cs
+++ b/src/BenchmarkDotNet/Disassemblers/DisassemblyDiagnoser.cs
@@ -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;
}
}
}
\ No newline at end of file
diff --git a/src/BenchmarkDotNet/Reports/Metric.cs b/src/BenchmarkDotNet/Reports/Metric.cs
index ad69edd13e..688e421571 100644
--- a/src/BenchmarkDotNet/Reports/Metric.cs
+++ b/src/BenchmarkDotNet/Reports/Metric.cs
@@ -32,6 +32,8 @@ public interface IMetricDescriptor
[PublicAPI] string Unit { get; }
[PublicAPI] bool TheGreaterTheBetter { get; }
+
+ [PublicAPI] int PriorityInCategory { get; }
}
public class MetricDescriptorEqualityComparer : EqualityComparer
diff --git a/tests/BenchmarkDotNet.Tests/Reports/FakeMetricDescriptor.cs b/tests/BenchmarkDotNet.Tests/Reports/FakeMetricDescriptor.cs
index aef9500879..c005345aba 100644
--- a/tests/BenchmarkDotNet.Tests/Reports/FakeMetricDescriptor.cs
+++ b/tests/BenchmarkDotNet.Tests/Reports/FakeMetricDescriptor.cs
@@ -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;
}
}
diff --git a/tests/BenchmarkDotNet.Tests/Reports/SummaryTests.cs b/tests/BenchmarkDotNet.Tests/Reports/SummaryTests.cs
index 8b44c4c264..8497f83bd4 100644
--- a/tests/BenchmarkDotNet.Tests/Reports/SummaryTests.cs
+++ b/tests/BenchmarkDotNet.Tests/Reports/SummaryTests.cs
@@ -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;
}
}
}