From 7c2ea71f2853b0c5da96732988494779ec179ab4 Mon Sep 17 00:00:00 2001 From: Parker Bibus Date: Thu, 26 Mar 2026 13:41:00 -0700 Subject: [PATCH 1/5] Update BenchmarkDotNet to 0.16.0-nightly.20260324.479 for verification testing --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 0621a70ae59..950907dd15d 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -11,7 +11,7 @@ 10.0.0-rc.1.25555.107 10.0.0-rc.1.25555.107 10.0.0-rc.1.25555.107 - 0.16.0-nightly.20260320.467 + 0.16.0-nightly.20260324.479 10.0.0-rc.1.25555.107 11.0.0-prerelease.26169.1 From 0d1bb358fe6ab8a52d62ef6d31cacae5d04ec39d Mon Sep 17 00:00:00 2001 From: Parker Bibus Date: Thu, 26 Mar 2026 21:29:08 -0700 Subject: [PATCH 2/5] Update BDN.Extensions harness for BDN 0.16.0 async API changes - PerfLabExporter: Changed from ExporterBase to implementing IExporter directly, added ExportAsync method to match new BDN async exporter API - UniqueArgumentsValidator, MandatoryCategoryValidator, TooManyTestCasesValidator, NoWasmValidator: Changed Validate() to ValidateAsync() returning IAsyncEnumerable These changes are required for BDN 0.16.0-nightly.20260324.479 which moved exporters and validators to async-only APIs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../MandatoryCategoryValidator.cs | 18 +++++++++-------- .../NoWasmValidator.cs | 18 +++++++++-------- .../PerfLabExporter.cs | 20 +++++++++++++------ .../TooManyTestCasesValidator.cs | 10 ++++++---- .../UniqueArgumentsValidator.cs | 13 ++++++++---- 5 files changed, 49 insertions(+), 30 deletions(-) diff --git a/src/harness/BenchmarkDotNet.Extensions/MandatoryCategoryValidator.cs b/src/harness/BenchmarkDotNet.Extensions/MandatoryCategoryValidator.cs index 7b3b2d38f3b..0d41292c6c0 100644 --- a/src/harness/BenchmarkDotNet.Extensions/MandatoryCategoryValidator.cs +++ b/src/harness/BenchmarkDotNet.Extensions/MandatoryCategoryValidator.cs @@ -21,15 +21,17 @@ public class MandatoryCategoryValidator : IValidator public MandatoryCategoryValidator(ImmutableHashSet categories) => _mandatoryCategories = categories; - public IEnumerable Validate(ValidationParameters validationParameters) - => validationParameters.Benchmarks + public async IAsyncEnumerable ValidateAsync(ValidationParameters validationParameters) + { + foreach (var benchmarkId in validationParameters.Benchmarks .Where(benchmark => !benchmark.Descriptor.Categories.Any(category => _mandatoryCategories.Contains(category))) .Select(benchmark => benchmark.Descriptor.GetFilterName()) - .Distinct() - .Select(benchmarkId => - new ValidationError( - isCritical: TreatsWarningsAsErrors, - $"{benchmarkId} does not belong to one of the mandatory categories: {string.Join(", ", _mandatoryCategories)}. Use [BenchmarkCategory(Categories.$)]") - ); + .Distinct()) + { + yield return new ValidationError( + isCritical: TreatsWarningsAsErrors, + $"{benchmarkId} does not belong to one of the mandatory categories: {string.Join(", ", _mandatoryCategories)}. Use [BenchmarkCategory(Categories.$)]"); + } + } } } \ No newline at end of file diff --git a/src/harness/BenchmarkDotNet.Extensions/NoWasmValidator.cs b/src/harness/BenchmarkDotNet.Extensions/NoWasmValidator.cs index 5b2cfec63ca..3d8bc5fe8af 100644 --- a/src/harness/BenchmarkDotNet.Extensions/NoWasmValidator.cs +++ b/src/harness/BenchmarkDotNet.Extensions/NoWasmValidator.cs @@ -23,16 +23,18 @@ public class NoWasmValidator : IValidator public NoWasmValidator(string noWasmCategory) => _noWasmCategory = noWasmCategory; - public IEnumerable Validate(ValidationParameters validationParameters) - => validationParameters.Benchmarks + public async IAsyncEnumerable ValidateAsync(ValidationParameters validationParameters) + { + foreach (var benchmarkId in validationParameters.Benchmarks .Where(benchmark => IsAsyncMethod(benchmark.Descriptor.WorkloadMethod) && !benchmark.Descriptor.Categories.Any(category => category.Equals(_noWasmCategory, StringComparison.Ordinal))) .Select(benchmark => benchmark.Descriptor.GetFilterName()) - .Distinct() - .Select(benchmarkId => - new ValidationError( - isCritical: TreatsWarningsAsErrors, - $"{benchmarkId} returns an awaitable object and has no: {_noWasmCategory} category applied. Use [BenchmarkCategory(Categories.NoWASM)]") - ); + .Distinct()) + { + yield return new ValidationError( + isCritical: TreatsWarningsAsErrors, + $"{benchmarkId} returns an awaitable object and has no: {_noWasmCategory} category applied. Use [BenchmarkCategory(Categories.NoWASM)]"); + } + } private bool IsAsyncMethod(MethodInfo workloadMethod) { diff --git a/src/harness/BenchmarkDotNet.Extensions/PerfLabExporter.cs b/src/harness/BenchmarkDotNet.Extensions/PerfLabExporter.cs index c1ed4268e0f..78dd538da3b 100644 --- a/src/harness/BenchmarkDotNet.Extensions/PerfLabExporter.cs +++ b/src/harness/BenchmarkDotNet.Extensions/PerfLabExporter.cs @@ -9,19 +9,25 @@ using Reporting; using System; using System.Linq; +using System.Threading; +using System.Threading.Tasks; namespace BenchmarkDotNet.Extensions { - public class PerfLabExporter : ExporterBase + /// + /// Exports benchmark results to JSON format for PerfLab ingestion. + /// + public class PerfLabExporter : IExporter { - protected override string FileExtension => "json"; - protected override string FileCaption => "perf-lab-report"; + public string Name => "PerfLab"; - public PerfLabExporter() + public async ValueTask ExportAsync(Summary summary, ILogger logger, CancellationToken cancellationToken) { + await Task.CompletedTask; + Export(summary, logger); } - public override void ExportToLog(Summary summary, ILogger logger) + public void Export(Summary summary, ILogger logger) { var reporter = new Reporter(); @@ -132,7 +138,9 @@ where result.IsOverhead() && result.IterationStage != Engines.IterationStage.Jit var jsonOutput = reporter.GetJson(); if (jsonOutput is not null) - logger.WriteLine(jsonOutput); + { + Console.WriteLine(jsonOutput); + } } } } diff --git a/src/harness/BenchmarkDotNet.Extensions/TooManyTestCasesValidator.cs b/src/harness/BenchmarkDotNet.Extensions/TooManyTestCasesValidator.cs index aaf8a62317a..560b13303fb 100644 --- a/src/harness/BenchmarkDotNet.Extensions/TooManyTestCasesValidator.cs +++ b/src/harness/BenchmarkDotNet.Extensions/TooManyTestCasesValidator.cs @@ -19,17 +19,19 @@ public class TooManyTestCasesValidator : IValidator public bool TreatsWarningsAsErrors => true; - public IEnumerable Validate(ValidationParameters validationParameters) + public async IAsyncEnumerable ValidateAsync(ValidationParameters validationParameters) { var byDescriptor = validationParameters.Benchmarks .Where(benchmark => !SkipValidation(benchmark.Descriptor.WorkloadMethod)) .GroupBy(benchmark => (benchmark.Descriptor, benchmark.Job)); // descriptor = type + method - return byDescriptor.Where(benchmarkCase => benchmarkCase.Count() > Limit).Select(group => - new ValidationError( + foreach (var group in byDescriptor.Where(benchmarkCase => benchmarkCase.Count() > Limit)) + { + yield return new ValidationError( isCritical: true, message: $"{group.Key.Descriptor.Type.Name}.{group.Key.Descriptor.WorkloadMethod.Name} has {group.Count()} test cases. It MUST NOT have more than {Limit} test cases. We don't have inifinite amount of time to run all the benchmarks!!", - benchmarkCase: group.First())); + benchmarkCase: group.First()); + } } private static bool SkipValidation(MemberInfo member) diff --git a/src/harness/BenchmarkDotNet.Extensions/UniqueArgumentsValidator.cs b/src/harness/BenchmarkDotNet.Extensions/UniqueArgumentsValidator.cs index 532e9b003f5..c9265bc67fa 100644 --- a/src/harness/BenchmarkDotNet.Extensions/UniqueArgumentsValidator.cs +++ b/src/harness/BenchmarkDotNet.Extensions/UniqueArgumentsValidator.cs @@ -14,8 +14,9 @@ public class UniqueArgumentsValidator : IValidator { public bool TreatsWarningsAsErrors => true; - public IEnumerable Validate(ValidationParameters validationParameters) - => validationParameters.Benchmarks + public async IAsyncEnumerable ValidateAsync(ValidationParameters validationParameters) + { + foreach (var error in validationParameters.Benchmarks .Where(benchmark => benchmark.HasArguments || benchmark.HasParameters) .GroupBy(benchmark => (benchmark.Descriptor.Type, benchmark.Descriptor.WorkloadMethod, benchmark.Job)) .Where(sameBenchmark => @@ -25,7 +26,11 @@ public IEnumerable Validate(ValidationParameters validationPara return numberOfTestCases != numberOfUniqueTestCases; }) - .Select(duplicate => new ValidationError(true, $"Benchmark Arguments should be unique, {duplicate.Key.Type}.{duplicate.Key.WorkloadMethod} has duplicate arguments.", duplicate.First())); + .Select(duplicate => new ValidationError(true, $"Benchmark Arguments should be unique, {duplicate.Key.Type}.{duplicate.Key.WorkloadMethod} has duplicate arguments.", duplicate.First()))) + { + yield return error; + } + } private class BenchmarkArgumentsComparer : IEqualityComparer { @@ -34,7 +39,7 @@ public bool Equals(BenchmarkCase x, BenchmarkCase y) if (FullNameProvider.GetBenchmarkName(x).Equals(FullNameProvider.GetBenchmarkName(y), System.StringComparison.Ordinal)) return true; - return Enumerable.SequenceEqual( + return System.Linq.Enumerable.SequenceEqual( x.Parameters.Items.Select(argument => argument.Value), y.Parameters.Items.Select(argument => argument.Value)); } From d1ae1e2adf5eb262a8f7225ea014046f75eeb2d5 Mon Sep 17 00:00:00 2001 From: Parker Bibus Date: Fri, 27 Mar 2026 10:16:14 -0700 Subject: [PATCH 3/5] Add Microsoft.Bcl.AsyncInterfaces package reference for netstandard2.0 The BDN.Extensions project targets netstandard2.0 and now uses IAsyncEnumerable from the updated BDN validator API. On netstandard2.0, IAsyncEnumerable requires the Microsoft.Bcl.AsyncInterfaces polyfill package. Version 10.0.5 matches the transitive dependency from BDN -> System.Linq.AsyncEnumerable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../BenchmarkDotNet.Extensions/BenchmarkDotNet.Extensions.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/harness/BenchmarkDotNet.Extensions/BenchmarkDotNet.Extensions.csproj b/src/harness/BenchmarkDotNet.Extensions/BenchmarkDotNet.Extensions.csproj index ef8782db2aa..b99ce85c2a3 100644 --- a/src/harness/BenchmarkDotNet.Extensions/BenchmarkDotNet.Extensions.csproj +++ b/src/harness/BenchmarkDotNet.Extensions/BenchmarkDotNet.Extensions.csproj @@ -11,6 +11,7 @@ + From ed282d845ac9b4df4e483996c3ea46e9427301cf Mon Sep 17 00:00:00 2001 From: Parker Bibus Date: Wed, 1 Apr 2026 15:18:12 -0700 Subject: [PATCH 4/5] Fix BDN 0.16.0 async validators to avoid deadlock with BDN SynchronizationContext Replace async IAsyncEnumerable yield-return pattern with synchronous IEnumerable wrapped via SyncAsyncEnumerable.AsAsyncEnumerable(). The async state machine generated by yield-return deadlocks with BDN's custom BenchmarkSynchronizationContext pump loop. Also add SyncAsyncEnumerable helper to avoid runtime dependency on System.Linq.AsyncEnumerable (pruned on .NET 10+) and ensure Microsoft.Bcl.AsyncInterfaces is deployed at runtime. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../BenchmarkDotNet.Extensions.csproj | 5 ++- .../MandatoryCategoryValidator.cs | 13 +++--- .../NoWasmValidator.cs | 13 +++--- .../PerfLabExporter.cs | 4 +- .../SyncAsyncEnumerable.cs | 43 +++++++++++++++++++ .../TooManyTestCasesValidator.cs | 16 +++---- .../UniqueArgumentsValidator.cs | 10 ++--- 7 files changed, 72 insertions(+), 32 deletions(-) create mode 100644 src/harness/BenchmarkDotNet.Extensions/SyncAsyncEnumerable.cs diff --git a/src/harness/BenchmarkDotNet.Extensions/BenchmarkDotNet.Extensions.csproj b/src/harness/BenchmarkDotNet.Extensions/BenchmarkDotNet.Extensions.csproj index b99ce85c2a3..b9183df3e86 100644 --- a/src/harness/BenchmarkDotNet.Extensions/BenchmarkDotNet.Extensions.csproj +++ b/src/harness/BenchmarkDotNet.Extensions/BenchmarkDotNet.Extensions.csproj @@ -11,7 +11,10 @@ - + + none + true + diff --git a/src/harness/BenchmarkDotNet.Extensions/MandatoryCategoryValidator.cs b/src/harness/BenchmarkDotNet.Extensions/MandatoryCategoryValidator.cs index 0d41292c6c0..82ec607c87f 100644 --- a/src/harness/BenchmarkDotNet.Extensions/MandatoryCategoryValidator.cs +++ b/src/harness/BenchmarkDotNet.Extensions/MandatoryCategoryValidator.cs @@ -21,17 +21,16 @@ public class MandatoryCategoryValidator : IValidator public MandatoryCategoryValidator(ImmutableHashSet categories) => _mandatoryCategories = categories; - public async IAsyncEnumerable ValidateAsync(ValidationParameters validationParameters) + public IAsyncEnumerable ValidateAsync(ValidationParameters validationParameters) { - foreach (var benchmarkId in validationParameters.Benchmarks + return validationParameters.Benchmarks .Where(benchmark => !benchmark.Descriptor.Categories.Any(category => _mandatoryCategories.Contains(category))) .Select(benchmark => benchmark.Descriptor.GetFilterName()) - .Distinct()) - { - yield return new ValidationError( + .Distinct() + .Select(benchmarkId => new ValidationError( isCritical: TreatsWarningsAsErrors, - $"{benchmarkId} does not belong to one of the mandatory categories: {string.Join(", ", _mandatoryCategories)}. Use [BenchmarkCategory(Categories.$)]"); - } + $"{benchmarkId} does not belong to one of the mandatory categories: {string.Join(", ", _mandatoryCategories)}. Use [BenchmarkCategory(Categories.$)]")) + .AsAsyncEnumerable(); } } } \ No newline at end of file diff --git a/src/harness/BenchmarkDotNet.Extensions/NoWasmValidator.cs b/src/harness/BenchmarkDotNet.Extensions/NoWasmValidator.cs index 3d8bc5fe8af..1ad9f7ef23a 100644 --- a/src/harness/BenchmarkDotNet.Extensions/NoWasmValidator.cs +++ b/src/harness/BenchmarkDotNet.Extensions/NoWasmValidator.cs @@ -23,17 +23,16 @@ public class NoWasmValidator : IValidator public NoWasmValidator(string noWasmCategory) => _noWasmCategory = noWasmCategory; - public async IAsyncEnumerable ValidateAsync(ValidationParameters validationParameters) + public IAsyncEnumerable ValidateAsync(ValidationParameters validationParameters) { - foreach (var benchmarkId in validationParameters.Benchmarks + return validationParameters.Benchmarks .Where(benchmark => IsAsyncMethod(benchmark.Descriptor.WorkloadMethod) && !benchmark.Descriptor.Categories.Any(category => category.Equals(_noWasmCategory, StringComparison.Ordinal))) .Select(benchmark => benchmark.Descriptor.GetFilterName()) - .Distinct()) - { - yield return new ValidationError( + .Distinct() + .Select(benchmarkId => new ValidationError( isCritical: TreatsWarningsAsErrors, - $"{benchmarkId} returns an awaitable object and has no: {_noWasmCategory} category applied. Use [BenchmarkCategory(Categories.NoWASM)]"); - } + $"{benchmarkId} returns an awaitable object and has no: {_noWasmCategory} category applied. Use [BenchmarkCategory(Categories.NoWASM)]")) + .AsAsyncEnumerable(); } private bool IsAsyncMethod(MethodInfo workloadMethod) diff --git a/src/harness/BenchmarkDotNet.Extensions/PerfLabExporter.cs b/src/harness/BenchmarkDotNet.Extensions/PerfLabExporter.cs index 78dd538da3b..104828ff982 100644 --- a/src/harness/BenchmarkDotNet.Extensions/PerfLabExporter.cs +++ b/src/harness/BenchmarkDotNet.Extensions/PerfLabExporter.cs @@ -21,10 +21,10 @@ public class PerfLabExporter : IExporter { public string Name => "PerfLab"; - public async ValueTask ExportAsync(Summary summary, ILogger logger, CancellationToken cancellationToken) + public ValueTask ExportAsync(Summary summary, ILogger logger, CancellationToken cancellationToken) { - await Task.CompletedTask; Export(summary, logger); + return default; } public void Export(Summary summary, ILogger logger) diff --git a/src/harness/BenchmarkDotNet.Extensions/SyncAsyncEnumerable.cs b/src/harness/BenchmarkDotNet.Extensions/SyncAsyncEnumerable.cs new file mode 100644 index 00000000000..281d1dd0a26 --- /dev/null +++ b/src/harness/BenchmarkDotNet.Extensions/SyncAsyncEnumerable.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace BenchmarkDotNet.Extensions +{ + /// + /// Wraps a synchronous as + /// without requiring System.Linq.AsyncEnumerable or Microsoft.Bcl.AsyncInterfaces packages + /// at runtime. This avoids package pruning issues on .NET 10+ where those polyfill packages + /// are removed but netstandard2.0 libraries still reference them. + /// + internal static class SyncAsyncEnumerable + { + public static IAsyncEnumerable AsAsyncEnumerable(this IEnumerable source) + => new Wrapper(source); + + private sealed class Wrapper : IAsyncEnumerable + { + private readonly IEnumerable _source; + public Wrapper(IEnumerable source) => _source = source; + public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + => new Enumerator(_source.GetEnumerator()); + } + + private sealed class Enumerator : IAsyncEnumerator + { + private readonly IEnumerator _inner; + public Enumerator(IEnumerator inner) => _inner = inner; + public T Current => _inner.Current; + public ValueTask MoveNextAsync() => new ValueTask(_inner.MoveNext()); + public ValueTask DisposeAsync() + { + _inner.Dispose(); + return default; + } + } + } +} diff --git a/src/harness/BenchmarkDotNet.Extensions/TooManyTestCasesValidator.cs b/src/harness/BenchmarkDotNet.Extensions/TooManyTestCasesValidator.cs index 560b13303fb..c92994630df 100644 --- a/src/harness/BenchmarkDotNet.Extensions/TooManyTestCasesValidator.cs +++ b/src/harness/BenchmarkDotNet.Extensions/TooManyTestCasesValidator.cs @@ -19,19 +19,17 @@ public class TooManyTestCasesValidator : IValidator public bool TreatsWarningsAsErrors => true; - public async IAsyncEnumerable ValidateAsync(ValidationParameters validationParameters) + public IAsyncEnumerable ValidateAsync(ValidationParameters validationParameters) { - var byDescriptor = validationParameters.Benchmarks + return validationParameters.Benchmarks .Where(benchmark => !SkipValidation(benchmark.Descriptor.WorkloadMethod)) - .GroupBy(benchmark => (benchmark.Descriptor, benchmark.Job)); // descriptor = type + method - - foreach (var group in byDescriptor.Where(benchmarkCase => benchmarkCase.Count() > Limit)) - { - yield return new ValidationError( + .GroupBy(benchmark => (benchmark.Descriptor, benchmark.Job)) + .Where(group => group.Count() > Limit) + .Select(group => new ValidationError( isCritical: true, message: $"{group.Key.Descriptor.Type.Name}.{group.Key.Descriptor.WorkloadMethod.Name} has {group.Count()} test cases. It MUST NOT have more than {Limit} test cases. We don't have inifinite amount of time to run all the benchmarks!!", - benchmarkCase: group.First()); - } + benchmarkCase: group.First())) + .AsAsyncEnumerable(); } private static bool SkipValidation(MemberInfo member) diff --git a/src/harness/BenchmarkDotNet.Extensions/UniqueArgumentsValidator.cs b/src/harness/BenchmarkDotNet.Extensions/UniqueArgumentsValidator.cs index c9265bc67fa..1e27ac3c713 100644 --- a/src/harness/BenchmarkDotNet.Extensions/UniqueArgumentsValidator.cs +++ b/src/harness/BenchmarkDotNet.Extensions/UniqueArgumentsValidator.cs @@ -14,9 +14,9 @@ public class UniqueArgumentsValidator : IValidator { public bool TreatsWarningsAsErrors => true; - public async IAsyncEnumerable ValidateAsync(ValidationParameters validationParameters) + public IAsyncEnumerable ValidateAsync(ValidationParameters validationParameters) { - foreach (var error in validationParameters.Benchmarks + return validationParameters.Benchmarks .Where(benchmark => benchmark.HasArguments || benchmark.HasParameters) .GroupBy(benchmark => (benchmark.Descriptor.Type, benchmark.Descriptor.WorkloadMethod, benchmark.Job)) .Where(sameBenchmark => @@ -26,10 +26,8 @@ public async IAsyncEnumerable ValidateAsync(ValidationParameter return numberOfTestCases != numberOfUniqueTestCases; }) - .Select(duplicate => new ValidationError(true, $"Benchmark Arguments should be unique, {duplicate.Key.Type}.{duplicate.Key.WorkloadMethod} has duplicate arguments.", duplicate.First()))) - { - yield return error; - } + .Select(duplicate => new ValidationError(true, $"Benchmark Arguments should be unique, {duplicate.Key.Type}.{duplicate.Key.WorkloadMethod} has duplicate arguments.", duplicate.First())) + .AsAsyncEnumerable(); } private class BenchmarkArgumentsComparer : IEqualityComparer From ad6983358c42f59e72f22a72ed345179cb0cc4b5 Mon Sep 17 00:00:00 2001 From: Parker Bibus Date: Mon, 6 Apr 2026 15:37:15 -0700 Subject: [PATCH 5/5] Replace custom SyncAsyncEnumerable with System.Linq.AsyncEnumerable.ToAsyncEnumerable() The custom SyncAsyncEnumerable wrapper caused a deadlock when running under BDN's BenchmarkSynchronizationContext. BDN's own validators use System.Linq.AsyncEnumerable's ToAsyncEnumerable() extension, so we align with that. Also suppressed NU1510 pruning warning for .NET 10+ targets. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../BenchmarkDotNet.Extensions.csproj | 5 +++ .../MandatoryCategoryValidator.cs | 2 +- .../NoWasmValidator.cs | 2 +- .../SyncAsyncEnumerable.cs | 43 ------------------- .../TooManyTestCasesValidator.cs | 2 +- .../UniqueArgumentsValidator.cs | 2 +- 6 files changed, 9 insertions(+), 47 deletions(-) delete mode 100644 src/harness/BenchmarkDotNet.Extensions/SyncAsyncEnumerable.cs diff --git a/src/harness/BenchmarkDotNet.Extensions/BenchmarkDotNet.Extensions.csproj b/src/harness/BenchmarkDotNet.Extensions/BenchmarkDotNet.Extensions.csproj index b9183df3e86..3bcb0a18441 100644 --- a/src/harness/BenchmarkDotNet.Extensions/BenchmarkDotNet.Extensions.csproj +++ b/src/harness/BenchmarkDotNet.Extensions/BenchmarkDotNet.Extensions.csproj @@ -4,6 +4,7 @@ netstandard2.0 enable true + $(NoWarn);NU1510 <_BenchmarkDotNetSourcesN>$([MSBuild]::NormalizeDirectory('$(BenchmarkDotNetSources)')) @@ -11,6 +12,10 @@ + + none + true + none true diff --git a/src/harness/BenchmarkDotNet.Extensions/MandatoryCategoryValidator.cs b/src/harness/BenchmarkDotNet.Extensions/MandatoryCategoryValidator.cs index 82ec607c87f..fadd193f8f8 100644 --- a/src/harness/BenchmarkDotNet.Extensions/MandatoryCategoryValidator.cs +++ b/src/harness/BenchmarkDotNet.Extensions/MandatoryCategoryValidator.cs @@ -30,7 +30,7 @@ public IAsyncEnumerable ValidateAsync(ValidationParameters vali .Select(benchmarkId => new ValidationError( isCritical: TreatsWarningsAsErrors, $"{benchmarkId} does not belong to one of the mandatory categories: {string.Join(", ", _mandatoryCategories)}. Use [BenchmarkCategory(Categories.$)]")) - .AsAsyncEnumerable(); + .ToAsyncEnumerable(); } } } \ No newline at end of file diff --git a/src/harness/BenchmarkDotNet.Extensions/NoWasmValidator.cs b/src/harness/BenchmarkDotNet.Extensions/NoWasmValidator.cs index 1ad9f7ef23a..d99620be0a2 100644 --- a/src/harness/BenchmarkDotNet.Extensions/NoWasmValidator.cs +++ b/src/harness/BenchmarkDotNet.Extensions/NoWasmValidator.cs @@ -32,7 +32,7 @@ public IAsyncEnumerable ValidateAsync(ValidationParameters vali .Select(benchmarkId => new ValidationError( isCritical: TreatsWarningsAsErrors, $"{benchmarkId} returns an awaitable object and has no: {_noWasmCategory} category applied. Use [BenchmarkCategory(Categories.NoWASM)]")) - .AsAsyncEnumerable(); + .ToAsyncEnumerable(); } private bool IsAsyncMethod(MethodInfo workloadMethod) diff --git a/src/harness/BenchmarkDotNet.Extensions/SyncAsyncEnumerable.cs b/src/harness/BenchmarkDotNet.Extensions/SyncAsyncEnumerable.cs deleted file mode 100644 index 281d1dd0a26..00000000000 --- a/src/harness/BenchmarkDotNet.Extensions/SyncAsyncEnumerable.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace BenchmarkDotNet.Extensions -{ - /// - /// Wraps a synchronous as - /// without requiring System.Linq.AsyncEnumerable or Microsoft.Bcl.AsyncInterfaces packages - /// at runtime. This avoids package pruning issues on .NET 10+ where those polyfill packages - /// are removed but netstandard2.0 libraries still reference them. - /// - internal static class SyncAsyncEnumerable - { - public static IAsyncEnumerable AsAsyncEnumerable(this IEnumerable source) - => new Wrapper(source); - - private sealed class Wrapper : IAsyncEnumerable - { - private readonly IEnumerable _source; - public Wrapper(IEnumerable source) => _source = source; - public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - => new Enumerator(_source.GetEnumerator()); - } - - private sealed class Enumerator : IAsyncEnumerator - { - private readonly IEnumerator _inner; - public Enumerator(IEnumerator inner) => _inner = inner; - public T Current => _inner.Current; - public ValueTask MoveNextAsync() => new ValueTask(_inner.MoveNext()); - public ValueTask DisposeAsync() - { - _inner.Dispose(); - return default; - } - } - } -} diff --git a/src/harness/BenchmarkDotNet.Extensions/TooManyTestCasesValidator.cs b/src/harness/BenchmarkDotNet.Extensions/TooManyTestCasesValidator.cs index c92994630df..bc4803e4ca1 100644 --- a/src/harness/BenchmarkDotNet.Extensions/TooManyTestCasesValidator.cs +++ b/src/harness/BenchmarkDotNet.Extensions/TooManyTestCasesValidator.cs @@ -29,7 +29,7 @@ public IAsyncEnumerable ValidateAsync(ValidationParameters vali isCritical: true, message: $"{group.Key.Descriptor.Type.Name}.{group.Key.Descriptor.WorkloadMethod.Name} has {group.Count()} test cases. It MUST NOT have more than {Limit} test cases. We don't have inifinite amount of time to run all the benchmarks!!", benchmarkCase: group.First())) - .AsAsyncEnumerable(); + .ToAsyncEnumerable(); } private static bool SkipValidation(MemberInfo member) diff --git a/src/harness/BenchmarkDotNet.Extensions/UniqueArgumentsValidator.cs b/src/harness/BenchmarkDotNet.Extensions/UniqueArgumentsValidator.cs index 1e27ac3c713..00a29353eb3 100644 --- a/src/harness/BenchmarkDotNet.Extensions/UniqueArgumentsValidator.cs +++ b/src/harness/BenchmarkDotNet.Extensions/UniqueArgumentsValidator.cs @@ -27,7 +27,7 @@ public IAsyncEnumerable ValidateAsync(ValidationParameters vali return numberOfTestCases != numberOfUniqueTestCases; }) .Select(duplicate => new ValidationError(true, $"Benchmark Arguments should be unique, {duplicate.Key.Type}.{duplicate.Key.WorkloadMethod} has duplicate arguments.", duplicate.First())) - .AsAsyncEnumerable(); + .ToAsyncEnumerable(); } private class BenchmarkArgumentsComparer : IEqualityComparer