Skip to content

Commit 42c7184

Browse files
Categories should have the highest priority in logical group order, fixes #1864
1 parent 9560515 commit 42c7184

File tree

4 files changed

+87
-5
lines changed

4 files changed

+87
-5
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
5+
namespace BenchmarkDotNet.Order
6+
{
7+
internal class CategoryComparer : IComparer<string[]>
8+
{
9+
private const string Separator = "§";
10+
public static readonly CategoryComparer Instance = new();
11+
12+
public int Compare(string[] x, string[] y)
13+
{
14+
return string.Compare(GetUniqueId(x), GetUniqueId(y), StringComparison.Ordinal);
15+
}
16+
17+
private static string GetUniqueId(string[] categories)
18+
{
19+
var list = categories.ToList();
20+
list.Sort();
21+
return string.Join(Separator, categories);
22+
}
23+
}
24+
}

src/BenchmarkDotNet/Order/DefaultOrderer.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public class DefaultOrderer : IOrderer
1616
{
1717
public static readonly IOrderer Instance = new DefaultOrderer();
1818

19+
private readonly IComparer<string[]> categoryComparer = CategoryComparer.Instance;
1920
private readonly IComparer<ParameterInstances> paramsComparer = ParameterComparer.Instance;
2021
private readonly IComparer<Job> jobComparer = JobComparer.Instance;
2122
private readonly IComparer<BenchmarkCase> benchmarkComparer;
@@ -31,7 +32,7 @@ public DefaultOrderer(
3132
SummaryOrderPolicy = summaryOrderPolicy;
3233
MethodOrderPolicy = methodOrderPolicy;
3334
IComparer<Descriptor> targetComparer = new DescriptorComparer(methodOrderPolicy);
34-
benchmarkComparer = new BenchmarkComparer(paramsComparer, jobComparer, targetComparer);
35+
benchmarkComparer = new BenchmarkComparer(categoryComparer, paramsComparer, jobComparer, targetComparer);
3536
logicalGroupComparer = new LogicalGroupComparer(benchmarkComparer);
3637
}
3738

@@ -103,14 +104,14 @@ public string GetLogicalGroupKey(ImmutableArray<BenchmarkCase> allBenchmarksCase
103104
}
104105

105106
var keys = new List<string>();
107+
if (rules.Contains(BenchmarkLogicalGroupRule.ByCategory))
108+
keys.Add(string.Join(",", benchmarkCase.Descriptor.Categories));
106109
if (rules.Contains(BenchmarkLogicalGroupRule.ByMethod))
107110
keys.Add(benchmarkCase.Descriptor.DisplayInfo);
108111
if (rules.Contains(BenchmarkLogicalGroupRule.ByJob))
109112
keys.Add(benchmarkCase.Job.DisplayInfo);
110113
if (rules.Contains(BenchmarkLogicalGroupRule.ByParams))
111114
keys.Add(benchmarkCase.Parameters.ValueInfo);
112-
if (rules.Contains(BenchmarkLogicalGroupRule.ByCategory))
113-
keys.Add(string.Join(",", benchmarkCase.Descriptor.Categories));
114115

115116
string logicalGroupKey = string.Join("-", keys.Where(key => key != string.Empty));
116117
return logicalGroupKey == string.Empty ? "*" : logicalGroupKey;
@@ -127,12 +128,18 @@ public virtual IEnumerable<IGrouping<string, BenchmarkCase>> GetLogicalGroupOrde
127128

128129
private class BenchmarkComparer : IComparer<BenchmarkCase>
129130
{
131+
private readonly IComparer<string[]> categoryComparer;
130132
private readonly IComparer<ParameterInstances> paramsComparer;
131133
private readonly IComparer<Job> jobComparer;
132134
private readonly IComparer<Descriptor> targetComparer;
133135

134-
public BenchmarkComparer(IComparer<ParameterInstances> paramsComparer, IComparer<Job> jobComparer, IComparer<Descriptor> targetComparer)
136+
public BenchmarkComparer(
137+
IComparer<string[]> categoryComparer,
138+
IComparer<ParameterInstances> paramsComparer,
139+
IComparer<Job> jobComparer,
140+
IComparer<Descriptor> targetComparer)
135141
{
142+
this.categoryComparer = categoryComparer;
136143
this.targetComparer = targetComparer;
137144
this.jobComparer = jobComparer;
138145
this.paramsComparer = paramsComparer;
@@ -145,6 +152,7 @@ public int Compare(BenchmarkCase x, BenchmarkCase y)
145152
if (x == null) return -1;
146153
return new[]
147154
{
155+
categoryComparer?.Compare(x.Descriptor.Categories, y.Descriptor.Categories) ?? 0,
148156
paramsComparer?.Compare(x.Parameters, y.Parameters) ?? 0,
149157
jobComparer?.Compare(x.Job, y.Job) ?? 0,
150158
targetComparer?.Compare(x.Descriptor, y.Descriptor) ?? 0,

src/BenchmarkDotNet/Running/BenchmarkCase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public class BenchmarkCase : IComparable<BenchmarkCase>, IDisposable
2020

2121
public override string ToString() => DisplayInfo;
2222

23-
private BenchmarkCase(Descriptor descriptor, Job job, ParameterInstances parameters, ImmutableConfig config)
23+
internal BenchmarkCase(Descriptor descriptor, Job job, ParameterInstances parameters, ImmutableConfig config)
2424
{
2525
Descriptor = descriptor;
2626
Job = job;
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Collections.Immutable;
4+
using System.Globalization;
5+
using System.Linq;
6+
using BenchmarkDotNet.Configs;
7+
using BenchmarkDotNet.Environments;
8+
using BenchmarkDotNet.Jobs;
9+
using BenchmarkDotNet.Order;
10+
using BenchmarkDotNet.Parameters;
11+
using BenchmarkDotNet.Reports;
12+
using BenchmarkDotNet.Running;
13+
using BenchmarkDotNet.Validators;
14+
using Xunit;
15+
16+
namespace BenchmarkDotNet.Tests.Order
17+
{
18+
public class DefaultOrdererTests
19+
{
20+
[Fact]
21+
public void CategoriesHasHigherPriorityThanParameters()
22+
{
23+
var summary = new Summary("", ImmutableArray<BenchmarkReport>.Empty, HostEnvironmentInfo.GetCurrent(),
24+
"", "", TimeSpan.Zero, CultureInfo.InvariantCulture, ImmutableArray<ValidationError>.Empty);
25+
26+
BenchmarkCase CreateBenchmarkCase(string category, int parameter) => new(
27+
new Descriptor(null, null, categories: new[] { category }),
28+
new Job(),
29+
new ParameterInstances(new[]
30+
{
31+
new ParameterInstance(new ParameterDefinition("P", false, null, false, null, 0), parameter, SummaryStyle.Default)
32+
}),
33+
DefaultConfig.Instance.CreateImmutableConfig()
34+
);
35+
36+
string GetId(BenchmarkCase benchmarkCase) => benchmarkCase.Descriptor.Categories.First() + benchmarkCase.Parameters.Items.First().Value;
37+
38+
var benchmarkCases = new List<BenchmarkCase>
39+
{
40+
CreateBenchmarkCase("A", 1),
41+
CreateBenchmarkCase("B", 1),
42+
CreateBenchmarkCase("A", 2),
43+
CreateBenchmarkCase("B", 2)
44+
}.ToImmutableArray();
45+
46+
string[] sortedBenchmarkCases = DefaultOrderer.Instance.GetSummaryOrder(benchmarkCases, summary).Select(GetId).ToArray();
47+
Assert.Equal(new[] {"A1", "A2", "B1", "B2"}, sortedBenchmarkCases);
48+
}
49+
}
50+
}

0 commit comments

Comments
 (0)