How far apart competing implementations of the same synchronization primitive typically land, for the benchmark run selected below. Every cell's ratio is that variant's mean time divided by the fastest ranked variant's mean time for the same primitive in that run — 1.00 is the winner, 2.00 means twice as slow. A n/c cell (see below) is shown for scale but held out of the ratio: it lacks something the others pay for on every call, so comparing times would be apples to beans. Both numbers come from the scenario closest to normal use - one contending party (not zero, and not a bare uncontended call some benchmark classes also record) with a live, uncancelled token where one was measured - rather than an average across every contention level a "Scaling by contention" chart would show: a "Multiple" benchmark's mean time at high contention is the time for many concurrent operations, not a per-operation cost, so blending it in would let whichever variant scales worst under load dominate the ratio.
Click a library to hide or show it. Pooled, Nito.AsyncEx, ProtoPromise, RefImpl and System stay pinned leftmost and can't be hidden.
Data source: benchmark-history.sqlite, generated at build time from the run
archive on the benchmarks branch. Ratios are computed from mean time, averaged per
(family, variant) across every method, contention level and cancellation state measured in the
selected run — see the trends dashboard for per-parameter detail, and
the library matrix for which library supports which primitive. The raw
baseline comparison table (Interlocked.*, lock(), SpinLock, SpinOnce) a few benchmark classes
measure alongside the real primitives isn't a synchronization primitive itself and is excluded
here.
n/c ("non-competing") marks a cell shown for scale but held out of the ratio -
its measured mean is in the tooltip, but it does not get a ratio and does not define the 1.00x
baseline: the vendored RefImpl reference implementation (no cancellation, no
timeout, no pooling); DotNext's AsyncExclusiveLock and reader-writer lock in the
lock rows (no disposable releaser, measured doing less work per operation); and "System" in the
AutoResetEvent, ManualResetEvent, Barrier and ReaderWriterLockSlim rows (a blocking wait). Same
idea as hors concours / ausser Konkurrenz.
† marks a "System" cell whose primitive may have no true async wait API - its
benchmark measures a blocking wait rather than an awaited one, so the ratio is a baseline
reference rather than a fair race against the async implementations in the other columns. (Where
that is definitely the case, the cell is n/c instead.)
‡ marks "ProtoPromise" - it builds on its own Promise/Promise<T> type and
its own cancellation token rather than System.Threading.Tasks.ValueTask and
CancellationToken, so it is not drop-in compatible with code written against the
BCL types the other columns share.