Skip to content

Commit c382cfd

Browse files
authored
feat: Change default job order to numeric order (#2933)
* feat: change default job order to numeric order * chore: remove JobOrderPolicy.Default and modify JobComparer constructor * chore: modify helper class access modifier * Add .NET10 tfm support and add modify unit tests
1 parent c9dec4d commit c382cfd

File tree

11 files changed

+56
-36
lines changed

11 files changed

+56
-36
lines changed

samples/BenchmarkDotNet.Samples/IntroOrderAttr.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace BenchmarkDotNet.Samples
66
{
7-
[Orderer(SummaryOrderPolicy.FastestToSlowest, MethodOrderPolicy.Declared, jobOrderPolicy: JobOrderPolicy.Default)]
7+
[Orderer(SummaryOrderPolicy.FastestToSlowest, MethodOrderPolicy.Declared, jobOrderPolicy: JobOrderPolicy.Numeric)]
88
[DryJob]
99
public class IntroOrderAttr
1010
{

src/BenchmarkDotNet/Attributes/OrdererAttribute.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public class OrdererAttribute : Attribute, IConfigSource
1010
public OrdererAttribute(
1111
SummaryOrderPolicy summaryOrderPolicy = SummaryOrderPolicy.Default,
1212
MethodOrderPolicy methodOrderPolicy = MethodOrderPolicy.Declared,
13-
JobOrderPolicy jobOrderPolicy = JobOrderPolicy.Default)
13+
JobOrderPolicy jobOrderPolicy = JobOrderPolicy.Numeric)
1414
{
1515
Config = ManualConfig.CreateEmpty().WithOrderer(new DefaultOrderer(summaryOrderPolicy, methodOrderPolicy, jobOrderPolicy));
1616
}

src/BenchmarkDotNet/BenchmarkDotNet.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<Import Project="..\..\build\common.props" />
33
<PropertyGroup>
44
<AssemblyTitle>BenchmarkDotNet</AssemblyTitle>
5-
<TargetFrameworks>netstandard2.0;net6.0;net8.0;net9.0</TargetFrameworks>
5+
<TargetFrameworks>netstandard2.0;net6.0;net8.0;net9.0;net10.0</TargetFrameworks>
66
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
77
<NoWarn>$(NoWarn);1701;1702;1705;1591;3005;NU1702;CS3001;CS3003</NoWarn>
88
<AssemblyName>BenchmarkDotNet</AssemblyName>

src/BenchmarkDotNet/Configs/ImmutableConfigBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ private static ImmutableHashSet<IValidator> GetValidators(IEnumerable<IValidator
221221
/// </summary>
222222
private static IReadOnlyList<Job> GetRunnableJobs(IEnumerable<Job> jobs)
223223
{
224-
var unique = jobs.Distinct(JobComparer.Instance).ToArray();
224+
var unique = jobs.Distinct(JobComparer.Default).ToArray();
225225
var result = new List<Job>();
226226

227227
foreach (var standardJob in unique.Where(job => !job.Meta.IsMutator && !job.Meta.IsDefault))

src/BenchmarkDotNet/Jobs/JobComparer.cs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,28 @@ namespace BenchmarkDotNet.Jobs
1010
internal class JobComparer : IComparer<Job>, IEqualityComparer<Job>
1111
{
1212
private readonly IComparer<string> Comparer;
13+
private static IComparer<string> NumericComparer =>
14+
#if NET10_0_OR_GREATER
15+
StringComparer.Create(System.Globalization.CultureInfo.InvariantCulture, System.Globalization.CompareOptions.NumericOrdering);
16+
#else
17+
new NumericStringComparer();
18+
#endif
1319

14-
public static readonly JobComparer Instance = new JobComparer(JobOrderPolicy.Default);
15-
public static readonly JobComparer Numeric = new JobComparer(JobOrderPolicy.Numeric);
20+
public static readonly JobComparer Default = new(JobOrderPolicy.Numeric);
21+
public static readonly JobComparer Ordinal = new(JobOrderPolicy.Ordinal);
1622

17-
public JobComparer(JobOrderPolicy jobOrderPolicy = JobOrderPolicy.Default)
23+
private JobComparer(JobOrderPolicy jobOrderPolicy)
1824
{
19-
Comparer = jobOrderPolicy == JobOrderPolicy.Default
20-
? StringComparer.Ordinal
21-
: new NumericStringComparer(); // TODO: Use `StringComparer.Create(CultureInfo.InvariantCulture, CompareOptions.NumericOrdering)` for .NET10 or greater.
25+
switch (jobOrderPolicy)
26+
{
27+
case JobOrderPolicy.Ordinal:
28+
Comparer = StringComparer.Ordinal;
29+
break;
30+
31+
default:
32+
Comparer = NumericComparer;
33+
break;
34+
}
2235
}
2336

2437
public int Compare(Job? x, Job? y)
@@ -66,7 +79,8 @@ public int Compare(Job? x, Job? y)
6679

6780
public int GetHashCode(Job obj) => obj.Id.GetHashCode();
6881

69-
internal class NumericStringComparer : IComparer<string>
82+
#if !NET10_0_OR_GREATER
83+
private class NumericStringComparer : IComparer<string>
7084
{
7185
public int Compare(string? x, string? y)
7286
{
@@ -139,5 +153,6 @@ public int Compare(string? x, string? y)
139153
return (spanX.Length - i).CompareTo(spanY.Length - j);
140154
}
141155
}
156+
#endif
142157
}
143158
}

src/BenchmarkDotNet/Order/DefaultOrderer.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ public class DefaultOrderer : IOrderer
2828
public DefaultOrderer(
2929
SummaryOrderPolicy summaryOrderPolicy = SummaryOrderPolicy.Default,
3030
MethodOrderPolicy methodOrderPolicy = MethodOrderPolicy.Declared,
31-
JobOrderPolicy jobOrderPolicy = JobOrderPolicy.Default)
31+
JobOrderPolicy jobOrderPolicy = JobOrderPolicy.Numeric)
3232
{
3333
SummaryOrderPolicy = summaryOrderPolicy;
3434
MethodOrderPolicy = methodOrderPolicy;
35-
jobComparer = jobOrderPolicy == JobOrderPolicy.Default
36-
? JobComparer.Instance
37-
: JobComparer.Numeric;
35+
jobComparer = jobOrderPolicy == JobOrderPolicy.Ordinal
36+
? JobComparer.Ordinal
37+
: JobComparer.Default;
3838
targetComparer = new DescriptorComparer(methodOrderPolicy);
3939
}
4040

src/BenchmarkDotNet/Order/JobOrderPolicy.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
public enum JobOrderPolicy
44
{
55
/// <summary>
6-
/// Compare job characteristics in ordinal order.
6+
/// Compare job characteristics in numeric order.
77
/// </summary>
8-
Default,
8+
Numeric,
99

1010
/// <summary>
11-
/// Compare job characteristics in numeric order.
11+
/// Compare job characteristics in ordinal order.
1212
/// </summary>
13-
Numeric,
13+
Ordinal,
1414
}

src/BenchmarkDotNet/Validators/BaselineValidator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public IEnumerable<ValidationError> Validate(ValidationParameters input)
3030
{
3131
var benchmarks = allBenchmarks.Where((benchmark, index) => benchmarkLogicalGroups[index] == logicalGroup).ToArray();
3232
int methodBaselineCount = benchmarks.Select(b => b.Descriptor).Distinct().Count(it => it.Baseline);
33-
int jobBaselineCount = benchmarks.Select(b => b.Job).Distinct(JobComparer.Instance).Count(it => it.Meta.Baseline);
33+
int jobBaselineCount = benchmarks.Select(b => b.Job).Distinct(JobComparer.Default).Count(it => it.Meta.Baseline);
3434
string className = benchmarks.First().Descriptor.Type.Name;
3535

3636
if (methodBaselineCount > 1)

tests/BenchmarkDotNet.Tests/BenchmarkDotNet.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<Import Project="..\..\build\common.props" />
33
<PropertyGroup>
44
<AssemblyTitle>BenchmarkDotNet.Tests</AssemblyTitle>
5-
<TargetFrameworks>net8.0;net462</TargetFrameworks>
5+
<TargetFrameworks>net8.0;net10.0;net462</TargetFrameworks>
66
<AssemblyName>BenchmarkDotNet.Tests</AssemblyName>
77
<PackageId>BenchmarkDotNet.Tests</PackageId>
88
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>

tests/BenchmarkDotNet.Tests/Order/JobOrderTests.cs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,27 @@ public void TestJobOrders_ByJobId()
2626
.WithId("v1.4.2"),
2727
];
2828

29-
// Verify jobs are sorted by JobId's ordinal order.
29+
// Verify jobs are sorted by JobId's default order (numeric order).
3030
{
3131
// Act
32-
var comparer = JobComparer.Instance;
32+
var comparer = JobComparer.Default;
3333
var results = jobs.OrderBy(x => x, comparer)
3434
.Select(x => x.Job.Id)
3535
.ToArray();
3636

3737
// Assert
38-
Assert.Equal(["v1.4.1", "v1.4.10", "v1.4.2"], results);
38+
Assert.Equal(["v1.4.1", "v1.4.2", "v1.4.10"], results);
3939
}
4040

41-
// Verify jobs are sorted by JobId's numeric order.
41+
// Verify jobs are sorted by JobId's ordinal order.
4242
{
4343
// Act
44-
var comparer = JobComparer.Numeric;
44+
var comparer = JobComparer.Ordinal;
4545
var results = jobs.OrderBy(d => d, comparer)
4646
.Select(x => x.Job.Id)
4747
.ToArray();
4848
// Assert
49-
Assert.Equal(["v1.4.1", "v1.4.2", "v1.4.10"], results);
49+
Assert.Equal(["v1.4.1", "v1.4.10", "v1.4.2"], results);
5050
}
5151
}
5252

@@ -65,8 +65,8 @@ public void TestJobOrders_ByRuntime()
6565
];
6666

6767
// Act
68-
// Verify jobs are sorted by Runtime's numeric order.
69-
var results = jobs.OrderBy(d => d, JobComparer.Numeric)
68+
// Verify jobs are sorted by Runtime name order.
69+
var results = jobs.OrderBy(d => d, JobComparer.Default)
7070
.Select(x => x.Job.Environment.GetRuntime().Name)
7171
.ToArray();
7272

@@ -92,8 +92,8 @@ public void TestJobOrders_ByToolchain()
9292
];
9393

9494
// Act
95-
// Verify jobs are sorted by Toolchain's numeric order.
96-
var results = jobs.OrderBy(d => d, JobComparer.Numeric)
95+
// Verify jobs are sorted by Toolchain name order.
96+
var results = jobs.OrderBy(d => d, JobComparer.Default)
9797
.Select(x => x.Job.GetToolchain().Name)
9898
.ToArray();
9999

@@ -132,12 +132,15 @@ public void TestJobOrders_ByToolchain()
132132
[InlineData(".NET 08", ".NET 10", -1)]
133133
[InlineData(".NET 10", ".NET 08", 1)]
134134
// Arguments that contains null
135-
[InlineData(null, "a", -1)]
136-
[InlineData("a", null, 1)]
137-
[InlineData(null, null, 0)]
138-
public void TestNumericComparer(string? a, string? b, int expectedSign)
135+
[InlineData("", "a", -1)]
136+
[InlineData("a", "", 1)]
137+
[InlineData("", "", 0)]
138+
public void TestNumericComparer(string a, string b, int expectedSign)
139139
{
140-
int result = new JobComparer.NumericStringComparer().Compare(a, b);
140+
var jobA = new Job(a);
141+
var jobB = new Job(b);
142+
143+
int result = JobComparer.Default.Compare(jobA, jobB);
141144
Assert.Equal(expectedSign, NormalizeSign(result));
142145

143146
static int NormalizeSign(int value)

0 commit comments

Comments
 (0)