Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
e930ff7
Async refactor
timcassell Dec 24, 2025
2244617
Async validation
timcassell Jan 5, 2026
c2bde2d
Merge branch 'master' into async-refactor
timcassell Jan 25, 2026
6f71ff4
Fix `CS0169` and `Could not load file or assembly Microsoft.Bcl.Async…
timcassell Jan 25, 2026
4094e33
Add thread-safety and wait-blocking to BenchmarkSynchronizationContext.
timcassell Jan 25, 2026
5524feb
Merge branch 'master' into async-refactor
timcassell Feb 1, 2026
3709747
IL emit match behavior of FieldsContainer conditional emit.
timcassell Feb 1, 2026
9242a9d
Reduce lock contention.
timcassell Feb 1, 2026
7e7e26b
Simplify argField names and remove unused constants.
timcassell Feb 1, 2026
62d575f
Fix race condition.
timcassell Feb 1, 2026
1e7b41c
Use async entry-point in wasm.
timcassell Feb 8, 2026
db34ae2
Made IExecutor.ExecuteAsync implementations truly async.
timcassell Feb 9, 2026
d87b530
Allow RoslynToolchain in old Mono.
timcassell Feb 9, 2026
6db0cde
Fix tests.
timcassell Feb 9, 2026
5423ea1
Catch proper exception on Unix.
timcassell Feb 9, 2026
c3d4529
Shorten pipe name.
timcassell Feb 9, 2026
0edf78a
Attempt to fix Windows hangs. Added pipe connection timeout.
timcassell Feb 9, 2026
53bdc54
Merge branch 'master' into async-refactor
timcassell Feb 10, 2026
5a465a8
Remove redundant check.
timcassell Feb 10, 2026
70a6b14
ReadLineAsync
timcassell Feb 10, 2026
48a307d
Use 2 pipes to fix deadlock.
timcassell Feb 10, 2026
3c082cc
Pluralize NamedPipesHost name.
timcassell Feb 10, 2026
d3fdd8e
Try read/write synchronously in the host.
timcassell Feb 12, 2026
fa7ecbb
Read/write synchronously on both ends.
timcassell Feb 12, 2026
00dc6d2
Change named pipes to TCP loopback.
timcassell Feb 13, 2026
4358883
Remove extra connect call. Catch known socket errors for early child …
timcassell Feb 13, 2026
4dfa2ce
Use synchronous read/write in child, synchronous write in parent.
timcassell Feb 14, 2026
3de0c6f
Make tcp host connect synchronously and change IHost methods back to …
timcassell Feb 14, 2026
f6c26ea
Merge branch 'master' into async-refactor
timcassell Feb 14, 2026
72196c5
Dispose client when process exited early.
timcassell Feb 14, 2026
7f2cd06
Backport Task.WaitAsync and StreamReader.ReadLineAsync with cancelati…
timcassell Feb 14, 2026
ade6d30
Use synchronous APIs on Full Framework + Windows Arm.
timcassell Feb 15, 2026
4656437
Add logs to find where the freeze is occurring.
timcassell Feb 16, 2026
4126c96
Check `awaiter.IsCompleted` instead of `valueTask.IsCompleted`. Moved…
timcassell Feb 16, 2026
ec874c7
Fix forever hang race condition.
timcassell Feb 16, 2026
d88b50e
Remove extra logs and revert IsFullFrameworkCompatibilityLayer.
timcassell Feb 16, 2026
e4bd4a4
Actual fix forever hang race condition.
timcassell Feb 17, 2026
b462278
Merge branch 'master' into async-refactor
timcassell Feb 17, 2026
d5b23e2
Add WebSocket IPC
timcassell Feb 17, 2026
6aa316a
Install ws
timcassell Feb 20, 2026
01bca09
Merge branch 'master' into async-refactor
timcassell Mar 5, 2026
68a97d0
Update wasm IPC to handle all engines.
timcassell Mar 7, 2026
ad7595b
Add cooperative cancelation and some cleanup.
timcassell Mar 8, 2026
ffafe00
Merge branch 'master' into async-refactor
timcassell Mar 8, 2026
8bb7b8f
Added [BenchmarkCancellation] attribute for users to participate in c…
timcassell Mar 8, 2026
24f89bd
Add code fixer.
timcassell Mar 8, 2026
f473599
Fix line endings.
timcassell Mar 8, 2026
fd8dc6f
Fix ExceptionHandlingTests
timcassell Mar 8, 2026
195070b
Fix NoHangs test.
timcassell Mar 9, 2026
e6430aa
Dispose WebSocketListener in case of exception.
timcassell Mar 9, 2026
6ce8bb5
Skip node tests in Framework.
timcassell Mar 9, 2026
bb012d7
Fix discoverer.
timcassell Mar 9, 2026
8387a1d
Update WebSocketListener and enable Framework tests.
timcassell Mar 9, 2026
1961870
Re-add v8 installation instructions.
timcassell Mar 10, 2026
2f934af
Refactor IDiagnoser, IBuilder, IGenerator to async.
timcassell Mar 14, 2026
995b78e
Update packages.
timcassell Mar 15, 2026
8343982
Update RunAsyncTests.
timcassell Mar 15, 2026
09190c4
Fix DisposeAtProcessTermination calling Dispose too early.
timcassell Mar 15, 2026
734c8ca
Fix child process deadlock after cancel.
timcassell Mar 15, 2026
16b00ea
Check if the token was canceled.
timcassell Mar 15, 2026
9dcf5d2
Refactor IExporter to async.
timcassell Mar 15, 2026
be6aa21
Fix ScottPlotExporterTests.
timcassell Mar 15, 2026
a4350c6
Fix ExceptionHelper methods and exception filters.
timcassell Mar 16, 2026
8637d0e
Use ConfigureAwait everywhere.
timcassell Mar 16, 2026
c5bbbeb
Some fixes.
timcassell Mar 16, 2026
3c46323
Replace magic string with constant.
timcassell Mar 16, 2026
ace6b4a
Fix InProcessNoEmitToolchain validation.
timcassell Mar 16, 2026
a195aaa
Fix usings.
timcassell Mar 16, 2026
8bd2a1a
Fix UserCodeRunsOnCallerThread test.
timcassell Mar 16, 2026
464caba
Refactor to make StreamOrLoggerWriter internal.
timcassell Mar 16, 2026
42d9dd7
Capture standard error.
timcassell Mar 16, 2026
eb07350
Remove file-based ipc timeout.
timcassell Mar 16, 2026
a8c8fa0
Fix test.
timcassell Mar 16, 2026
7620a76
Use async file streams.
timcassell Mar 22, 2026
b1b53e6
RPlotExporter LoadTemplateAsync
timcassell Mar 22, 2026
f8b2c54
Move all process cleanup logic to ProcessCleanupHelper and use it eve…
timcassell Mar 22, 2026
479dbc4
Fix base dispose call.
timcassell Mar 22, 2026
5aea465
Fixes from AI code review.
timcassell Mar 23, 2026
58dd6ce
Remove extra blank line.
timcassell Mar 23, 2026
4b89172
More small fixes.
timcassell Mar 23, 2026
f48a7f7
Fix comment.
timcassell Mar 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 6 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[*.cs]

# CS1998: Async method lacks 'await' operators and will run synchronously
dotnet_diagnostic.CS1998.severity = suggestion
# CA2007: Consider calling ConfigureAwait on the awaited task
dotnet_diagnostic.CA2007.severity = warning
4 changes: 4 additions & 0 deletions BenchmarkDotNet.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@
<Project Path="samples/BenchmarkDotNet.Samples.FSharp/BenchmarkDotNet.Samples.FSharp.fsproj" />
<Project Path="samples/BenchmarkDotNet.Samples/BenchmarkDotNet.Samples.csproj" DefaultStartup="true" />
</Folder>
<Folder Name="/Solution Items/">
<File Path=".editorconfig" />
</Folder>
<Folder Name="/src/">
<Project Path="src/BenchmarkDotNet.Analyzers/BenchmarkDotNet.Analyzers.csproj" />
<Project Path="src/BenchmarkDotNet.Annotations/BenchmarkDotNet.Annotations.csproj" />
<Project Path="src/BenchmarkDotNet.CodeFixers/BenchmarkDotNet.CodeFixers.csproj" />
<Project Path="src/BenchmarkDotNet.Diagnostics.dotMemory/BenchmarkDotNet.Diagnostics.dotMemory.csproj" />
<Project Path="src/BenchmarkDotNet.Diagnostics.dotTrace/BenchmarkDotNet.Diagnostics.dotTrace.csproj" />
<Project Path="src/BenchmarkDotNet.Diagnostics.Windows/BenchmarkDotNet.Diagnostics.Windows.csproj" />
Expand Down
2 changes: 2 additions & 0 deletions build/BenchmarkDotNet.Build/BuildContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class BuildContext : FrostingContext

public FilePath SolutionFile { get; }
public FilePath AnalyzersProjectFile { get; }
public FilePath CodeFixersProjectFile { get; }
public FilePath TemplatesTestsProjectFile { get; }
public FilePathCollection AllPackableSrcProjects { get; }
public FilePath VersionsFile { get; }
Expand Down Expand Up @@ -66,6 +67,7 @@ public BuildContext(ICakeContext context)

SolutionFile = RootDirectory.CombineWithFilePath("BenchmarkDotNet.slnx");
AnalyzersProjectFile = RootDirectory.Combine("src").Combine("BenchmarkDotNet.Analyzers").CombineWithFilePath("BenchmarkDotNet.Analyzers.csproj");
CodeFixersProjectFile = RootDirectory.Combine("src").Combine("BenchmarkDotNet.CodeFixers").CombineWithFilePath("BenchmarkDotNet.CodeFixers.csproj");

TemplatesTestsProjectFile = RootDirectory.Combine("templates")
.CombineWithFilePath("BenchmarkDotNet.Templates.csproj");
Expand Down
14 changes: 10 additions & 4 deletions build/BenchmarkDotNet.Build/Runners/BuildRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using Cake.Common.Tools.DotNet.Workload.Install;
using Cake.Core;
using Cake.Core.IO;
using System;
using System.IO;
using System.Linq;

Expand Down Expand Up @@ -51,7 +50,6 @@ public void PackWeaver()
{
MSBuildSettings = context.MsBuildSettingsRestore,
};
MaybeAppendArgument(restoreSettings);
context.DotNetRestore(weaverPath.GetDirectory().FullPath, restoreSettings);

context.Information("BuildSystemProvider: " + context.BuildSystem().Provider);
Expand All @@ -63,7 +61,6 @@ public void PackWeaver()
Configuration = context.BuildConfiguration,
Verbosity = context.BuildVerbosity
};
MaybeAppendArgument(buildSettings);
context.DotNetBuild(weaverPath.FullPath, buildSettings);

var packSettings = new DotNetPackSettings
Expand All @@ -72,7 +69,6 @@ public void PackWeaver()
MSBuildSettings = context.MsBuildSettingsPack,
Configuration = context.BuildConfiguration
};
MaybeAppendArgument(packSettings);
context.DotNetPack(weaverPath.FullPath, packSettings);
}

Expand Down Expand Up @@ -140,6 +136,16 @@ public void BuildAnalyzers()
Verbosity = context.BuildVerbosity,
ArgumentCustomization = args => args.Append($"-p:MccVersion={version}")
});

context.DotNetBuild(context.CodeFixersProjectFile.FullPath, new DotNetBuildSettings
{
NoRestore = true,
DiagnosticOutput = true,
MSBuildSettings = context.MsBuildSettingsBuild,
Configuration = context.BuildConfiguration,
Verbosity = context.BuildVerbosity,
ArgumentCustomization = args => args.Append($"-p:MccVersion={version}")
});
}
}

Expand Down
2 changes: 1 addition & 1 deletion build/common.props
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@

<PropertyGroup>
<!-- Increment this when the BenchmarkDotNet.Weaver package needs to be re-packed. -->
<WeaverVersionSuffix>-3</WeaverVersionSuffix>
<WeaverVersionSuffix>-4</WeaverVersionSuffix>
</PropertyGroup>

<ItemGroup>
Expand Down
46 changes: 46 additions & 0 deletions docs/articles/features/cancellation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Cooperative Cancellation in Benchmarks

BenchmarkDotNet supports cooperative cancellation, allowing benchmarks to gracefully respond to cancellation requests such as Ctrl+C.

## CancellationToken Injection

For long-running individual benchmark iterations, you can make your benchmarks cooperatively cancellable by marking a property or field with the `[BenchmarkCancellation]` attribute:

[!code-csharp[IntroCancellationToken.cs](../../../samples/BenchmarkDotNet.Samples/IntroCancellationToken.cs)]

You can also use a field instead of a property:

```csharp
public class MyBenchmarks
{
[BenchmarkCancellation]
public CancellationToken CancellationToken;

[Benchmark]
public async Task MyBenchmark()
{
await Task.Delay(100, CancellationToken);
}
}
```

## How It Works

1. **Attribute Detection**: BenchmarkDotNet automatically detects properties or fields marked with `[BenchmarkCancellation]`
2. **Automatic Injection**: Before running benchmarks, the framework injects the current cancellation token
3. **Cooperative Checking**: Your benchmark code passes the token to async methods or calls `ThrowIfCancellationRequested()`

## Best Practices

1. **Pass to async methods**: Pass the token to async framework methods that already support cancellation
2. **Don't swallow cancellation**: Let `OperationCanceledException` propagate
3. **Check periodically in tight loops**: For CPU-bound loops, check every N iterations to balance responsiveness and overhead

## Requirements

Properties and fields marked with `[BenchmarkCancellation]` must be:
- Of type `System.Threading.CancellationToken`
- Public
- For properties: must have a public setter (init-only setters are supported)

Both static and instance members are supported.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<PackageReference Include="System.IO.Hashing" Version="[$(SihVersion)]" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.5" />
<PackageReference Include="System.Drawing.Common" Version="10.0.3" />
<!-- The Test SDK is required only for the VSTest Adapter to work -->
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
Expand Down
32 changes: 32 additions & 0 deletions samples/BenchmarkDotNet.Samples/IntroCancellationToken.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Threading;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;

namespace BenchmarkDotNet.Samples;

/// <summary>
/// Demonstrates cooperative cancellation using [BenchmarkCancellation] attribute.
/// When a benchmark class has a property or field marked with [BenchmarkCancellation], BenchmarkDotNet automatically
/// injects the cancellation token, allowing benchmarks to check for cancellation during execution.
/// This is useful for long-running async benchmarks that should respond to Ctrl+C or other cancellation signals.
/// </summary>
public class IntroCancellationToken
{
[BenchmarkCancellation]
public CancellationToken CancellationToken { get; set; }

[Benchmark]
public async Task AsyncBenchmark()
{
for (int i = 0; i < 100; i++)
{
await DoWorkAsync(CancellationToken);
}
}

private async Task DoWorkAsync(CancellationToken cancellationToken)
{
// Simulate some async work
await Task.Delay(100, cancellationToken);
}
}
1 change: 1 addition & 0 deletions samples/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
<PropertyGroup>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
<IsPackable>false</IsPackable>
<NoWarn>$(NoWarn);CA2007</NoWarn>
</PropertyGroup>
</Project>
6 changes: 6 additions & 0 deletions src/BenchmarkDotNet.Analyzers/AnalyzerReleases.Unshipped.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
Rule ID | Category | Severity | Notes
---------|----------|----------|--------------------
BDN1305 | Usage | Error | [ParamsSource] cannot reference write-only property
BDN1600 | Usage | Error | Fields or properties annotated with [BenchmarkCancellation] must be of type CancellationToken
BDN1601 | Usage | Error | Fields annotated with [BenchmarkCancellation] must be public
BDN1602 | Usage | Error | Properties annotated with [BenchmarkCancellation] must be public
BDN1603 | Usage | Error | [BenchmarkCancellation] attribute is not valid on readonly fields
BDN1604 | Usage | Error | Properties annotated with [BenchmarkCancellation] must have a public setter
BDN1605 | Usage | Info | Async benchmarks should have a [BenchmarkCancellation] property for cancellation support


### Removed Rules
Expand Down
Loading
Loading