forked from dotnet/BenchmarkDotNet
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Allocation Ratio column (dotnet#1859)
Co-authored-by: Adam Sitnik <[email protected]>
- Loading branch information
1 parent
f00f7c7
commit 9560515
Showing
5 changed files
with
119 additions
and
15 deletions.
There are no files selected for viewing
88 changes: 88 additions & 0 deletions
88
src/BenchmarkDotNet/Columns/BaselineAllocationRatioColumn.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using BenchmarkDotNet.Diagnosers; | ||
using BenchmarkDotNet.Mathematics; | ||
using BenchmarkDotNet.Reports; | ||
using BenchmarkDotNet.Running; | ||
using JetBrains.Annotations; | ||
|
||
namespace BenchmarkDotNet.Columns | ||
{ | ||
public class BaselineAllocationRatioColumn : BaselineCustomColumn | ||
{ | ||
public override string Id => nameof(BaselineAllocationRatioColumn); | ||
public override string ColumnName => "Alloc Ratio"; | ||
|
||
public override string GetValue(Summary summary, BenchmarkCase benchmarkCase, Statistics baseline, IReadOnlyDictionary<string, Metric> baselineMetrics, | ||
Statistics current, IReadOnlyDictionary<string, Metric> currentMetrics, bool isBaseline) | ||
{ | ||
double? ratio = GetAllocationRatio(currentMetrics, baselineMetrics); | ||
double? invertedRatio = GetAllocationRatio(baselineMetrics, currentMetrics); | ||
|
||
if (ratio == null) | ||
return "NA"; | ||
|
||
var cultureInfo = summary.GetCultureInfo(); | ||
var ratioStyle = summary?.Style?.RatioStyle ?? RatioStyle.Value; | ||
|
||
bool advancedPrecision = IsNonBaselinesPrecise(summary, baselineMetrics, benchmarkCase); | ||
switch (ratioStyle) | ||
{ | ||
case RatioStyle.Value: | ||
return ratio.Value.ToString(advancedPrecision ? "N3" : "N2", cultureInfo); | ||
case RatioStyle.Percentage: | ||
return isBaseline | ||
? "" | ||
: ratio.Value >= 1.0 | ||
? "+" + ((ratio.Value - 1.0) * 100).ToString(advancedPrecision ? "N1" : "N0", cultureInfo) + "%" | ||
: "-" + ((1.0 - ratio.Value) * 100).ToString(advancedPrecision ? "N1" : "N0", cultureInfo) + "%"; | ||
case RatioStyle.Trend: | ||
return isBaseline | ||
? "" | ||
: ratio.Value >= 1.0 | ||
? ratio.Value.ToString(advancedPrecision ? "N3" : "N2", cultureInfo) + "x more" | ||
: invertedRatio == null | ||
? "NA" | ||
: invertedRatio.Value.ToString(advancedPrecision ? "N3" : "N2", cultureInfo) + "x less"; | ||
default: | ||
throw new ArgumentOutOfRangeException(nameof(summary), ratioStyle, "RatioStyle is not supported"); | ||
} | ||
} | ||
|
||
private static bool IsNonBaselinesPrecise(Summary summary, IReadOnlyDictionary<string, Metric> baselineMetric, BenchmarkCase benchmarkCase) | ||
{ | ||
string logicalGroupKey = summary.GetLogicalGroupKey(benchmarkCase); | ||
var nonBaselines = summary.GetNonBaselines(logicalGroupKey); | ||
return nonBaselines.Any(c => GetAllocationRatio(summary[c].Metrics, baselineMetric) is > 0 and < 0.01); | ||
} | ||
|
||
private static double? GetAllocationRatio( | ||
[CanBeNull] IReadOnlyDictionary<string, Metric> current, | ||
[CanBeNull] IReadOnlyDictionary<string, Metric> baseline) | ||
{ | ||
double? currentBytes = GetAllocatedBytes(current); | ||
double? baselineBytes = GetAllocatedBytes(baseline); | ||
|
||
if (currentBytes == null || baselineBytes == null) | ||
return null; | ||
|
||
if (baselineBytes == 0) | ||
return null; | ||
|
||
return currentBytes / baselineBytes; | ||
} | ||
|
||
private static double? GetAllocatedBytes([CanBeNull] IReadOnlyDictionary<string, Metric> metrics) | ||
{ | ||
var metric = metrics?.Values.FirstOrDefault(m => m.Descriptor is AllocatedMemoryMetricDescriptor); | ||
return metric?.Value; | ||
} | ||
|
||
public override ColumnCategory Category => ColumnCategory.Metric; //it should be displayed after Allocated column | ||
public override int PriorityInCategory => AllocatedMemoryMetricDescriptor.Instance.PriorityInCategory + 1; | ||
public override bool IsNumeric => true; | ||
public override UnitType UnitType => UnitType.Dimensionless; | ||
public override string Legend => "Allocated memory ratio distribution ([Current]/[Baseline])"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
src/BenchmarkDotNet/Diagnosers/AllocatedMemoryMetricDescriptor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
using System; | ||
using BenchmarkDotNet.Columns; | ||
using BenchmarkDotNet.Reports; | ||
|
||
namespace BenchmarkDotNet.Diagnosers | ||
{ | ||
internal class AllocatedMemoryMetricDescriptor : IMetricDescriptor | ||
{ | ||
internal static readonly IMetricDescriptor Instance = new AllocatedMemoryMetricDescriptor(); | ||
|
||
public string Id => "Allocated Memory"; | ||
public string DisplayName => "Allocated"; | ||
public string Legend => "Allocated memory per single operation (managed only, inclusive, 1KB = 1024B)"; | ||
public string NumberFormat => "0.##"; | ||
public UnitType UnitType => UnitType.Size; | ||
public string Unit => SizeUnit.B.Name; | ||
public bool TheGreaterTheBetter => false; | ||
public int PriorityInCategory => GC.MaxGeneration + 1; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters