NBenchmark 0.35.0

dotnet add package NBenchmark --version 0.35.0
                    
NuGet\Install-Package NBenchmark -Version 0.35.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="NBenchmark" Version="0.35.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="NBenchmark" Version="0.35.0" />
                    
Directory.Packages.props
<PackageReference Include="NBenchmark" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add NBenchmark --version 0.35.0
                    
#r "nuget: NBenchmark, 0.35.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package NBenchmark@0.35.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=NBenchmark&version=0.35.0
                    
Install as a Cake Addin
#tool nuget:?package=NBenchmark&version=0.35.0
                    
Install as a Cake Tool

NBenchmark

Build NuGet Version NuGet Downloads .NET License: MIT

Straightforward benchmarking for .NET.

Benchmarking code sounds simple - run it, time it, compare. In practice the numbers are easy to get wrong: the JIT compiler is still optimizing your method during the first runs, the timer can cost more than a fast method, a single GC pause or OS context switch skews an average, and a 2% improvement you were sure you measured can be statistical noise.

NBenchmark takes care of the statistical analysis. One line of code gives you a calibrated, warmed-up, outlier-trimmed result with a confidence interval.

var result = Benchmark.Run(() => MandelbrotCalculation(name: "Mandelbrot calculation"));
result.Print();

NBenchmark console output showing median, mean, P95, P99, StdDev, CV, and confidence interval for a benchmark

Why NBenchmark?

  • No setup required. Benchmark.Run(() => ...) - no attributes, no class structure, no dedicated project. Drop it into a console app, a test, or a scratchpad.

  • Adaptive measurement. No iteration counts to guess. The engine calibrates ops-per-sample for fast methods so timer overhead doesn't dominate, and detects when warmup has plateaued so the JIT has settled. Pin any dimension when you want a fixed, reproducible run.

  • Statistical rigor built in. Samples stream until the 95% confidence interval is tight enough, then stop. IQR-fence outlier trimming filters OS noise, with a bimodal-distribution warning when discarded samples look like real latency spikes rather than random jitter. A/B comparisons use a Mann-Whitney U test with Cliff's delta effect size (Negligible / Small / Medium / Large), automatically switching to Kruskal-Wallis for three or more implementations.

  • Pluggable statistics. Swap in your own outlier detector (IOutlierDetector) or significance test (ISignificanceTest) when the built-in IQR/MAD trimming and rank-based tests don't fit your domain.

  • Low-overhead execution. The measurement loop is reflection-free and uses typed delegates to avoid virtual dispatch and boxing during timing, so the JIT optimizes your benchmark body as it would in production.

  • Async-native. Measures the true duration of Task and Task<T> work without sync-over-async wrappers.

  • Compile-time analysis. The optional NBenchmark.Analyzers package catches common benchmark authoring mistakes - dead code elimination, implicit order dependence, missing return values - as Roslyn diagnostics during build, before you ever run a measurement.

Installation

dotnet add package NBenchmark

Optional packages

Package Purpose
NBenchmark.Analyzers Roslyn analyzers that catch authoring mistakes at build time
NBenchmark.DependencyInjection Constructor injection for benchmark classes
NBenchmark.Reporters.Console Rich terminal tables via Spectre.Console
NBenchmark.Integration.xUnit Enforce performance thresholds as xUnit tests
NBenchmark.Integration.NUnit Enforce performance thresholds as NUnit tests
NBenchmark.Integration.MSTest Enforce performance thresholds as MSTest tests

Four modes, one engine

1. Single mode

The fastest way to get a reliable number.

var result = Benchmark.Run(() => int.Parse("12345"));
Console.WriteLine($"P95: {result.GetPercentile(0.95)} ns, Alloc: {result.MeanAllocatedBytes} B");

var result = await Benchmark.RunAsync(async () => await FetchDataAsync());

2. Suite mode

Compare multiple implementations with a fluent API.

var results = await new BenchmarkSuite("string concat")
    .Add("plus operator", () => "a" + "b" + "c")
    .Add("interpolation",  () => $"{"a"}{"b"}{"c"}")
    .WithBaseline("plus operator")
    .WithReporter(new ConsoleReporter())
    .RunAsync();

The output includes a Ratio column and a in the Sig column when the speed difference is statistically significant.

3. Harness mode

Attribute-based discovery with a CLI, for dedicated benchmark projects.

public class StringBenchmarks
{
    [Benchmark(Baseline = true)]
    public string Concat() => "a" + "b" + "c";

    [Benchmark]
    public string Interpolate() => $"{"a"}{"b"}{"c"}";
}

await BenchmarkHarness.Create(args)
    .AddFromAssembly<StringBenchmarks>()
    .WithReporter(new ConsoleReporter())
    .RunAsync();
dotnet run -- --filter StringBenchmarks.Concat  # Run a specific benchmark
dotnet run -- --dry-run                         # Validate wiring without running
dotnet run -- --reporter json                   # Output results for CI/CD

4. Global tool

Install once, benchmark any assembly with [Benchmark] methods - no project needed.

dotnet tool install -g NBenchmark.Tool
dotnet benchmark --project ./MyApp.Benchmarks
dotnet benchmark --assembly ./bin/Release/net10.0/MyLib.dll

All harness CLI flags pass through (--filter, --reporter, --output, --threshold-pct, etc.).

Features

  • Parameterized benchmarks. Run the same body across multiple input values to see how an algorithm scales - WithParameter in Suite mode, [BenchmarkCase] in Harness mode. (Suite / Harness)
  • Categories. Tag benchmarks with [BenchmarkCategory] and include or exclude groups from a run via CLI flags or the programmatic filter API. (Categories)
  • Isolated runs. Run benchmarks in freshly spawned child processes so JIT, GC, and thread-pool state from earlier work can't bias later measurements; isolated by default in Harness mode. (Isolated runs)
  • Multi-runtime comparison. Build and run the same benchmarks across net8, net9, and net10 in separate child processes and compare side-by-side. (Multi-runtime)
  • Multiple launches. Repeat each benchmark as independent launches to surface run-to-run variance and produce cross-launch aggregation stats. (Multiple launches)
  • Environment control. Pin CPU affinity, raise process priority, and detect noisy hosts to reduce measurement noise at its source. (Environment control)
  • Performance gates in CI. Enforce absolute or relative performance thresholds as xUnit, NUnit, or MSTest tests that fail on regression. (Test integration)
  • CI regression gate. Fail the harness run with a non-zero exit code when any benchmark regresses beyond a percentage against the baseline (--threshold-pct). (CLI reference)
  • Runtime diagnostics. Record GC collection counts, heap state, exceptions, and CPU time per operation alongside timings. (Diagnostics)
  • Live telemetry. Stream per-sample, per-phase, and per-detector events to an IMeasurementObserver, or export spans and metrics to OpenTelemetry via the built-in System.Diagnostics instrumentation. (Observers / OTel)

View the full documentation at nbenchmark.net.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages (6)

Showing the top 5 NuGet packages that depend on NBenchmark:

Package Downloads
NBenchmark.Integration.Abstractions

Shared abstractions and reusable building blocks for NBenchmark integration packages.

NBenchmark.DependencyInjection

Resolves benchmark classes from an IServiceProvider so they can have constructor dependencies.

NBenchmark.Reporters.Console

Rich terminal table output for NBenchmark using Spectre.Console.

NBenchmark.Integration.NUnit

Run NBenchmark benchmarks as NUnit tests with configurable performance thresholds.

NBenchmark.Integration.MSTest

Run NBenchmark benchmarks as MSTest tests with configurable performance thresholds.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.35.0 46 7/25/2026
0.34.0 73 7/25/2026
0.33.0 178 7/22/2026
0.32.1 179 7/22/2026
0.32.0 199 7/21/2026
0.31.0 201 7/20/2026
0.30.3 211 7/20/2026
0.30.2 206 7/20/2026
0.30.1 202 7/20/2026
0.30.0 212 7/19/2026
0.29.0 212 7/19/2026
0.28.1 205 7/19/2026
0.28.0 204 7/18/2026
0.27.1 224 7/9/2026
0.27.0 219 7/7/2026
0.26.0 221 6/30/2026
0.25.1 219 6/26/2026
0.25.0 225 6/26/2026
0.24.0 225 6/25/2026
0.23.0 224 6/25/2026
Loading failed