build: add BenchmarkDotNet baseline project for test doubles (#80, #102)#167
Merged
Conversation
This was referenced Jun 23, 2026
This was referenced Jun 26, 2026
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stands up a BenchmarkDotNet baseline project for the ETL Test Kit's runtime test doubles, satisfying #80 (stand up a BDN baseline project) and #102 (hold benchmarks to
TreatWarningsAsErrorsvia a curatedbenchmarks/.editorconfig, with nobenchmarks/Directory.Build.propsexemption).The project
benchmarks/Wolfgang.Etl.TestKit.Benchmarks/— anExetargetingnet10.0,LangVersion=latest,ImplicitUsings=disable, with aProjectReferencetoWolfgang.Etl.TestKitand a singleBenchmarkDotNet0.15.8 package reference.Program.csuses the standardBenchmarkSwitcher.FromAssembly(...).Run(args)entry point. Analyzer package references are inherited from the rootDirectory.Build.props(comment noted in the csproj). Added toETL-Test-Kit.slnxunder the/benchmarks/folder.Three benchmark classes
Each is
[MemoryDiagnoser], with[Params(1_000, 10_000, 100_000)] public int ItemCountand a[GlobalSetup]that builds an in-memoryint[].T = intkeeps allocations dominated by the framework path rather than record construction. One representative benchmark per class is[Benchmark(Baseline = true)].ExtractorBenchmarks.Extract—new TestExtractor<int>(int[])thenawait foreachoverExtractAsync().LoaderBenchmarks.Load—new TestLoader<int>(collectItems: false)thenawait loader.LoadAsync(source).TransformerBenchmarks.Transform—new TestTransformer<int>()thenawait foreachoverTransformAsync(source).#102 — held to TreatWarningsAsErrors
There is no
benchmarks/Directory.Build.props. The benchmark project inherits the rootDirectory.Build.props, so it IS held toTreatWarningsAsErrorsin Release. The only relaxation is a curatedbenchmarks/.editorconfigsilencing genuinely benchmark-inappropriate analyzer rules, each with a one-line justification:AsyncFixer01— remove async/await; benchmark methods follow BDN conventions.MA0004—ConfigureAwait(false)not needed in the benchmark harness.S1215—GC.GetTotalMemoryis required by memory benchmarks.VSTHRD200— Async suffix; benchmark method names follow BDN naming conventions.This matches the curated FixedWidth set exactly — no additional rule IDs were needed; the Release build is clean (0 warnings, 0 errors) against the full analyzer set.
IAsyncEnumerable source
Rather than depend on
System.Linq.Async's.ToAsyncEnumerable()(a transitive dep), the loader and transformer benchmarks use a tiny localasync IAsyncEnumerable<int>generator helper, keeping the source self-contained and the measured pipeline obvious.Verification
dotnet build benchmarks/Wolfgang.Etl.TestKit.Benchmarks/... -c Release→ Build succeeded, 0 Warning(s), 0 Error(s).dotnet run -c Release --project benchmarks/... -- --list flatlists all three benchmarks.dotnet run -c Release --project benchmarks/... -- --filter '*Extract*' --job dryexecutes and emits a summary table with the MemoryDiagnoserAllocatedcolumn (e.g. ~520 B/op across all three ItemCount params), confirming the harness runs.Closes #80
Closes #102
🤖 Generated with Claude Code