Home

Project

Release Notes

Current Release Notes

Breaking: DI container is now Microsoft.Extensions.DependencyInjection

Sailfish has moved off Autofac onto the standard .NET DI abstraction (IServiceCollection / IServiceProvider). Implement IRegisterSailfishServices in place of IProvideARegistrationCallback, and use IServiceCollection.AddSailfish(runSettings) in place of ContainerBuilder.RegisterSailfishTypes(runSettings). The Autofac package is no longer a dependency. Migration guide →

.NET 10 support, .NET 8 dropped

Sailfish, Sailfish.TestAdapter, and Sailfish.Analyzers now target net9.0 and net10.0 only. If you're on net8.0, stay on Sailfish 0.0.115 or upgrade your project.

Behavior change: OperationsPerInvoke reports per-operation time

When OperationsPerInvoke > 1 (set explicitly, or chosen by TargetIterationDurationMs auto-tuning), Sailfish now divides each measured iteration by the batch size, so reported mean/median/etc. represent the cost of a single operation and stay comparable across methods and runs regardless of the batch size. Previously the per-iteration aggregate was reported, which inflated results by the OPI factor. If you use OPI > 1, expect reported durations to drop accordingly — they now reflect true per-op cost. If you persist tracking data for SailDiff history on OPI > 1 tests, baselines recorded before this change will read as a one-time drop; re-baseline after upgrading. Learn more →

Feature: steady-state warmup (opt-in)

[Sailfish(UseSteadyStateWarmup = true)] warms up until per-iteration timing stops trending and stabilizes (tiered JIT/OSR has settled) rather than using a fixed count — bounded by NumWarmupIterations (floor) and MaxWarmupIterations (cap, default 50), stopping early when stable. Default off; the fixed-count warmup path is unchanged. Learn more →

Performance: compiled-delegate invocation

The timed method is now invoked through a compiled, allocation-free delegate instead of per-call reflection. On .NET 10 this drops per-invocation harness overhead from ~40 ns to ~1.5 ns and eliminates per-call allocations (272 B → 0 B); the overhead baseline is measured with a structurally identical idle delegate so the subtraction cancels almost exactly. The result is a lower, more stable noise floor, so Sailfish resolves smaller differences. Behavior note: a method returning Task/ValueTask without the async keyword is now correctly awaited and timed (previously under-measured). Learn more →

Feature: Configuration Recipes via SailfishPreset

RunSettingsBuilder.WithPreset(SailfishPreset.Default | Tight | Relaxed) seeds adaptive sampling, outlier handling, and SailDiff defaults from a single call. Learn more →

Feature: RunOnce on method setup/teardown

[SailfishMethodSetup(nameof(Foo), nameof(Bar), RunOnce = true)] invokes a setup/teardown at most once per executor run, even when multiple MethodNames are listed. Learn more →

Fix: Method-comparison failure handling

Failed members of a comparison group now publish TestOutcome.Failed (no more silent TestOutcome.None) and don't block sibling members from completing the comparison batch. Learn more →

Feature highlight: Timer Calibration + Jitter Score

Captures timer resolution and baseline overhead, computes a 0–100 Jitter Score from dispersion, and surfaces it in Markdown, the manifest, and Environment Health (Timer Jitter). Learn more →

Feature highlight: Precision/Time Budget Controller

Helps tests finish within per-method time budgets by conservatively relaxing precision targets when enabled. Learn more →

Feature highlight: Environment Health Check

Validates your benchmarking environment and appends a health summary to each test’s Output window. Learn more →

Release notes have been moved to GitHub Releases for better integration with the development workflow.

📋 View All Releases →

Why the Move?

  • Real-time updates: Release notes are now automatically generated when new versions are published
  • Better GitHub integration: Releases are prominently displayed on the repository page
  • Automatic linking: Direct links to commits, pull requests, and contributors
  • Asset management: NuGet packages are directly attached to each release
  • Notifications: Subscribe to release notifications on GitHub
Previous
Example App