Overview
Codebelt.Extensions.BenchmarkDotNet defines the repository-facing workspace model that the rest of this library family builds on. It packages a configurable BenchmarkWorkspaceOptions object, a default BenchmarkWorkspace implementation for locating benchmark assemblies and moving generated artifacts, and DI registration helpers for wiring the workspace into an application.
The package focuses on repeatable BenchmarkDotNet execution inside a normal repository layout. It standardizes where benchmark projects are discovered, where reports are written, and how BenchmarkDotNet configuration is applied, without forcing each runner to reimplement those conventions.
Key APIs
BenchmarkWorkspaceOptions is the main configuration surface. It initializes a default BenchmarkDotNet configuration, resolves a repository path and target framework moniker, exposes the tuning and reports folder names, and lets callers opt into Debug builds or skipping benchmarks that already have reports.
BenchmarkWorkspaceOptions.Slim is the package's built-in job preset. It reduces warmup count, shortens iteration time, caps iteration counts, and disables power-plan enforcement so callers can start from a faster baseline than BenchmarkDotNet's broader defaults.
BenchmarkWorkspaceOptionsExtensions.ConfigureBenchmarkDotNet applies fluent BenchmarkDotNet configuration without losing the returned IConfig instance. That matters because APIs such as AddJob, AddColumn, and AddDiagnoser return updated configurations instead of mutating the incoming one in place.
BenchmarkWorkspace is the default IBenchmarkWorkspace implementation. It validates options, adjusts the configuration for Debug builds when requested, loads benchmark assemblies from the configured tuning tree by suffix, build configuration, and target framework moniker, and moves finished report files from the BenchmarkDotNet results folder into the tuning folder.
BenchmarkWorkspace.GetReportsResultsPath and BenchmarkWorkspace.GetReportsTuningPath expose the package's artifact path conventions. Both methods validate the supplied options and derive their paths from Configuration.ArtifactsPath, which keeps file layout decisions centralized.
ServiceCollectionExtensions.AddBenchmarkWorkspace<TWorkspace> registers a workspace implementation and the configured BenchmarkWorkspaceOptions as singletons. Use it when a runner should resolve IBenchmarkWorkspace through IServiceCollection instead of manually constructing the workspace.
IBenchmarkWorkspace is the contract that separates benchmark discovery from benchmark execution. Custom runners or host layers can implement it when they need a different assembly-loading or artifact-post-processing strategy than BenchmarkWorkspace provides.
Basic usage
using System;
using System.IO;
using Codebelt.Extensions.BenchmarkDotNet;
using Codebelt.Extensions.Xunit;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace MyProject.Tests;
public class BenchmarkWorkspaceUsageTests : Test
{
public BenchmarkWorkspaceUsageTests(ITestOutputHelper output) : base(output)
{
}
[Fact]
public void ServiceCollection_RegistersWorkspaceAndRepositoryLayout()
{
var services = new ServiceCollection();
services.AddBenchmarkWorkspace(options =>
{
options.RepositoryPath = Path.Combine(Path.GetTempPath(), "inventory-benchmarks");
options.RepositoryReportsFolder = "reports";
options.RepositoryTuningFolder = "tuning";
});
using var provider = services.BuildServiceProvider();
var workspace = provider.GetRequiredService<IBenchmarkWorkspace>();
var options = provider.GetRequiredService<BenchmarkWorkspaceOptions>();
options.PostConfigureOptions();
var resultsPath = BenchmarkWorkspace.GetReportsResultsPath(options);
var tuningPath = BenchmarkWorkspace.GetReportsTuningPath(options);
TestOutput.WriteLines($"Workspace type: {workspace.GetType().Name}", $"Results path: {resultsPath}", $"Tuning path: {tuningPath}");
Assert.IsType<BenchmarkWorkspace>(workspace);
Assert.EndsWith(Path.Combine("reports", "results"), resultsPath, StringComparison.OrdinalIgnoreCase);
Assert.EndsWith(Path.Combine("reports", "tuning"), tuningPath, StringComparison.OrdinalIgnoreCase);
}
}
Use this pattern when your benchmark runner is assembled through dependency injection and still needs one shared repository layout for reports and tuning artifacts. It matters because the package keeps workspace registration, option binding, and derived artifact paths aligned with the same conventions the runner will execute against.
Installation
dotnet add package Codebelt.Extensions.BenchmarkDotNet
Usage guidance
Adopt this package when your repository needs a reusable benchmark workspace with explicit folder conventions, configurable BenchmarkDotNet settings, and DI-friendly composition. If you only need to call BenchmarkDotNet directly in a small one-off benchmark project, the plain BenchmarkDotNet APIs can be simpler than introducing the repository workspace abstraction.