Table of Contents

macOS ARM64 Apple M4 Threading Benchmarks

Machine Profile

Machine Specification

The benchmarks were run on the following machine:

BenchmarkDotNet v0.15.8, macOS Tahoe 26.3.1 (a) (25D771280a) [Darwin 25.3.0]
Apple M4, 1 CPU, 10 logical and 10 physical cores
.NET SDK 10.0.201
[Host]    : .NET 10.0.5 (10.0.5, 10.0.526.15411), Arm64 RyuJIT armv8.0-a
.NET 10.0 : .NET 10.0.5 (10.0.5, 10.0.526.15411), Arm64 RyuJIT armv8.0-a
Job=.NET 10.0  Runtime=.NET 10.0  Toolchain=net10.0
Alloc Ratio=NA

Note: Results are machine-specific and may vary between systems. Run benchmarks locally for your specific hardware.

BenchmarkDotNet microbenchmarks for all async synchronization primitives in CryptoHives.Foundation.Threading. Benchmarks cover uncontested fast paths (0 other waiters), single-waiter async round trips (1 waiter), and high-contention scenarios (10–100 waiters). All implementations are tested with both a default CancellationToken.None and a non-cancelled CancellationToken to isolate the registration overhead.

Implementations are compared against:

  • Pooled — CryptoHives pooled ValueTask-returning implementation (the baseline, ratio = 1.00)
  • ProtoPromise — ProtoPromise zero-allocation async primitives
  • RefImpl — Simple reference implementation using TaskCompletionSource<bool> (demonstrates heap-allocating baselines)
  • Nito.AsyncEx — Nito.AsyncEx async synchronization primitives (Stephen Cleary)
  • NeoSmart — NeoSmart.AsyncLock
  • VS.Threading / NonKeyed — Microsoft.VisualStudio.Threading / non-keyed async lock variants
  • System — .NET built-in synchronization primitives (SemaphoreSlim, ReaderWriterLockSlim, CountdownEvent, Barrier, ManualResetEventSlim, ManualResetEvent, AutoResetEvent)

Highlights

Primitive vs Windows Key Insight
AsyncAutoResetEvent (Set) ~34% faster ARM64 fast path; System.AutoResetEvent ~4× cheaper than on Windows
AsyncBarrier (1 participant) ~39% faster System.Barrier ~4× cheaper on macOS than Windows at P=1
AsyncCountdownEvent (1 participant) ~28% faster Pooled near-parity with System.CountdownEvent
AsyncLock (single) ~9% faster CryptoHives SpinLock ~20× faster than System.SpinLock
AsyncManualResetEvent (SetReset) ~21% faster ManualResetEvent kernel ~4× cheaper on macOS than Windows
AsyncRWLock (reader, uncontested) ~2× faster Strongest uncontested advantage; inverts under high contention
AsyncRWLock (writer, uncontested) ~34% faster Near-parity with ProtoPromise
AsyncSemaphore ~30% faster System.SemaphoreSlim ~½ the cost of Windows
Note

On Apple M4, the Pooled AsTask() path is 2–3× slower than on Windows x64 for low-contention scenarios (1–2 waiters). This reflects Windows ThreadPool's faster inline Task continuation scheduling. However, at 100 waiters the macOS AsTask path becomes faster — the Windows ThreadPool saturates first. For latency-sensitive code, prefer AsValueTask() or direct ValueTask consumption.


AsyncLock

AsyncLock provides exclusive mutual exclusion with cancellation support. The Single benchmark measures the uncontested acquire+release cycle with no other waiters. The Multiple benchmark adds a configurable number of concurrent contending waiters.

Single (uncontested)

The uncontested benchmark is a proxy for the underlying lock and ValueTask state machine cost when the fast path does not need to suspend. The CryptoHives SpinLock matches the speed of .NET's Lock.EnterScope — both roughly 20× faster than System.SpinLock due to the absence of OS kernel yield in the non-contended case. The async Pooled path is the fastest async lock on this platform.

Key observations:

  • Pooled: Fastest async lock; ~9% faster than Windows x64
  • ProtoPromise: ~12–15% faster than Pooled at this baseline (zero-allocation, no cancellation support)
  • System.Lock / lock(): both ~3–4× cheaper than async paths (no await overhead)
  • CryptoHives SpinLock: matches System.Lock; suitable only for very short critical sections
  • Nito and NeoSmart: each allocate per-lock (320 B / 208 B respectively); in the order-of-magnitude slower range
Description Mean Ratio Allocated
Lock · Interlocked.Exchange · System 0.0000 ns 0.000 -
Lock · Increment · System 0.4435 ns 0.059 -
Lock · Interlocked.Add · System 0.4573 ns 0.060 -
Lock · Interlocked.Inc · System 0.4583 ns 0.061 -
Lock · Interlocked.CmpX · System 2.4091 ns 0.318 -
Lock · Lock · System 2.6142 ns 0.345 -
Lock · Lock.EnterScope · System 2.6513 ns 0.350 -
SpinLock · SpinLock · CryptoHives 2.7340 ns 0.361 -
Lock · lock() · System 3.2074 ns 0.423 -
LockAsync · AsyncLock · ProtoPromise 6.6302 ns 0.875 -
LockAsync · AsyncLock · Pooled 7.5745 ns 1.000 -
LockAsync · AsyncSemaphore · VS.Threading 11.6188 ns 1.534 -
LockAsync · AsyncLock · RefImpl 11.7976 ns 1.558 -
LockAsync · SemaphoreSlim · System 12.7817 ns 1.688 -
LockAsync · AsyncLock · NonKeyed 16.6770 ns 2.202 -
LockAsync · AsyncLock · Nito.AsyncEx 40.3838 ns 5.332 320 B
SpinWait · SpinOnce · System 47.4733 ns 6.268 -
LockAsync · AsyncLock · NeoSmart 49.8415 ns 6.580 208 B
SpinLock · SpinLock · System 53.7720 ns 7.099 -

Multiple (contended)

The Multiple benchmark drives Iterations concurrent waiters through a single lock. Iteration = 0 is the uncontested baseline; Iteration = 1 introduces one additional waiter triggering an actual async suspension and resume; 10 and 100 measure contention scaling.

Key observations:

  • Pooled (ValueTask): Fastest async lock path at all contention levels
  • At 1 contender: Pooled (VT) leads; ProtoPromise ~20% slower; SemaphoreSlim ~55% slower
  • Pooled (AsTask) at 1 contender: ~2.9× slower than Windows. Task continuation scheduling via macOS ThreadPool is slower for a single resume. Prefer AsValueTask().
  • At 100 contenders: Pooled (VT) ~29% faster than Windows for the ValueTask path
  • Nito and VS.Threading scale poorly under NotCancelled cancellation due to CancellationToken.Register overhead
Description Iterations cancellationType Mean Ratio Allocated
Multiple · AsyncLock · Pooled (ValueTask) 0 None 7.891 ns 1.00 -
Multiple · AsyncLock · ProtoPromise 0 None 9.628 ns 1.22 -
Multiple · AsyncLock · Pooled (Task) 0 None 9.871 ns 1.25 -
Multiple · AsyncSemaphore · VS.Threading 0 None 12.949 ns 1.64 -
Multiple · AsyncLock · RefImpl 0 None 13.427 ns 1.70 -
Multiple · SemaphoreSlim · System 0 None 14.463 ns 1.83 -
Multiple · AsyncLock · NonKeyed 0 None 18.020 ns 2.28 -
Multiple · AsyncLock · Nito 0 None 41.402 ns 5.25 320 B
Multiple · AsyncLock · NeoSmart 0 None 52.997 ns 6.72 208 B
Multiple · AsyncLock · Pooled (ValueTask) 0 NotCancelled 8.057 ns 1.00 -
Multiple · AsyncLock · ProtoPromise 0 NotCancelled 10.232 ns 1.27 -
Multiple · AsyncLock · Pooled (Task) 0 NotCancelled 10.256 ns 1.27 -
Multiple · AsyncSemaphore · VS.Threading 0 NotCancelled 12.621 ns 1.57 -
Multiple · SemaphoreSlim · System 0 NotCancelled 14.560 ns 1.81 -
Multiple · AsyncLock · NonKeyed 0 NotCancelled 18.759 ns 2.33 -
Multiple · AsyncLock · Nito 0 NotCancelled 41.284 ns 5.12 320 B
Multiple · AsyncLock · NeoSmart 0 NotCancelled 52.493 ns 6.52 208 B
Multiple · AsyncLock · Pooled (ValueTask) 1 None 23.490 ns 1.00 -
Multiple · AsyncLock · ProtoPromise 1 None 28.130 ns 1.20 -
Multiple · SemaphoreSlim · System 1 None 37.045 ns 1.58 88 B
Multiple · AsyncSemaphore · VS.Threading 1 None 54.599 ns 2.32 168 B
Multiple · AsyncLock · RefImpl 1 None 68.697 ns 2.92 216 B
Multiple · AsyncLock · Nito 1 None 94.316 ns 4.02 728 B
Multiple · AsyncLock · NeoSmart 1 None 109.366 ns 4.66 416 B
Multiple · AsyncLock · NonKeyed 1 None 1,216.363 ns 51.79 350 B
Multiple · AsyncLock · Pooled (Task) 1 None 1,381.198 ns 58.80 271 B
Multiple · AsyncLock · Pooled (ValueTask) 1 NotCancelled 36.277 ns 1.00 -
Multiple · AsyncLock · ProtoPromise 1 NotCancelled 44.412 ns 1.22 -
Multiple · AsyncSemaphore · VS.Threading 1 NotCancelled 63.203 ns 1.74 168 B
Multiple · AsyncLock · NeoSmart 1 NotCancelled 107.268 ns 2.96 416 B
Multiple · AsyncLock · Nito 1 NotCancelled 646.678 ns 17.83 968 B
Multiple · AsyncLock · Pooled (Task) 1 NotCancelled 1,484.811 ns 40.93 272 B
Multiple · AsyncLock · NonKeyed 1 NotCancelled 1,498.509 ns 41.31 640 B
Multiple · SemaphoreSlim · System 1 NotCancelled 1,598.035 ns 44.05 504 B
Multiple · AsyncLock · ProtoPromise 10 None 197.073 ns 0.82 -
Multiple · AsyncLock · Pooled (ValueTask) 10 None 240.851 ns 1.00 -
Multiple · SemaphoreSlim · System 10 None 253.671 ns 1.05 880 B
Multiple · AsyncSemaphore · VS.Threading 10 None 451.128 ns 1.87 1680 B
Multiple · AsyncLock · Nito 10 None 565.469 ns 2.35 4400 B
Multiple · AsyncLock · RefImpl 10 None 567.840 ns 2.36 2160 B
Multiple · AsyncLock · NeoSmart 10 None 578.067 ns 2.40 2288 B
Multiple · AsyncLock · NonKeyed 10 None 7,081.010 ns 29.40 2296 B
Multiple · AsyncLock · Pooled (Task) 10 None 8,263.349 ns 34.31 1352 B
Multiple · AsyncLock · ProtoPromise 10 NotCancelled 339.757 ns 0.90 -
Multiple · AsyncLock · Pooled (ValueTask) 10 NotCancelled 377.674 ns 1.00 -
Multiple · AsyncSemaphore · VS.Threading 10 NotCancelled 552.628 ns 1.46 1680 B
Multiple · AsyncLock · NeoSmart 10 NotCancelled 572.761 ns 1.52 2288 B
Multiple · AsyncLock · Nito 10 NotCancelled 5,022.693 ns 13.30 6800 B
Multiple · AsyncLock · Pooled (Task) 10 NotCancelled 8,764.494 ns 23.21 1352 B
Multiple · SemaphoreSlim · System 10 NotCancelled 10,892.329 ns 28.84 3888 B
Multiple · AsyncLock · NonKeyed 10 NotCancelled 10,994.378 ns 29.11 5176 B
Multiple · AsyncLock · ProtoPromise 100 None 1,824.031 ns 0.81 -
Multiple · SemaphoreSlim · System 100 None 2,212.582 ns 0.98 8800 B
Multiple · AsyncLock · Pooled (ValueTask) 100 None 2,252.599 ns 1.00 -
Multiple · AsyncSemaphore · VS.Threading 100 None 4,467.492 ns 1.98 21120 B
Multiple · AsyncLock · NeoSmart 100 None 4,974.090 ns 2.21 21008 B
Multiple · AsyncLock · RefImpl 100 None 5,289.120 ns 2.35 21600 B
Multiple · AsyncLock · Nito 100 None 5,310.252 ns 2.36 41120 B
Multiple · AsyncLock · NonKeyed 100 None 51,740.124 ns 22.97 21738 B
Multiple · AsyncLock · Pooled (Task) 100 None 52,126.799 ns 23.14 12158 B
Multiple · AsyncLock · ProtoPromise 100 NotCancelled 3,179.227 ns 0.90 -
Multiple · AsyncLock · Pooled (ValueTask) 100 NotCancelled 3,519.580 ns 1.00 -
Multiple · AsyncLock · NeoSmart 100 NotCancelled 5,035.855 ns 1.43 21008 B
Multiple · AsyncSemaphore · VS.Threading 100 NotCancelled 5,525.962 ns 1.57 21120 B
Multiple · AsyncLock · Pooled (Task) 100 NotCancelled 60,399.318 ns 17.16 12155 B
Multiple · AsyncLock · Nito 100 NotCancelled 62,085.556 ns 17.64 65120 B
Multiple · SemaphoreSlim · System 100 NotCancelled 81,425.204 ns 23.14 37736 B
Multiple · AsyncLock · NonKeyed 100 NotCancelled 93,239.964 ns 26.50 50542 B

AsyncAutoResetEvent

AsyncAutoResetEvent releases exactly one waiter per Set() call. Three benchmarks cover: Set (no waiters — measures pure signal cost), SetThenWait (signal then immediately wait on the newly-reset event), and WaitThenSet (N waiters await then are unblocked one by one).

Set (no waiters)

The Set benchmark captures the cost of signaling an event that no one is waiting on — effectively a conditional interlocked operation plus any bookkeeping.

Key observations:

  • Pooled and ProtoPromise: sub-nanosecond pure-signal cost
  • System.AutoResetEvent (kernel): ~120× slower than Pooled; ~4× cheaper than on Windows
  • Apple Silicon mach_semaphore signaling is significantly cheaper than Windows kernel event objects
Description Mean Ratio Allocated
Set · AsyncAutoReset · ProtoPromise 0.3773 ns 0.83 -
Set · AsyncAutoReset · Pooled 0.4524 ns 1.00 -
Set · AsyncAutoReset · RefImpl 2.9948 ns 6.62 -
Set · AsyncAutoReset · Nito.AsyncEx 3.3905 ns 7.49 -
Set · AutoResetEvent · System 55.3979 ns 122.45 -

SetThenWait

Signals then immediately calls WaitAsync. Because the event was just set, WaitAsync returns synchronously — this measures the combined signal + synchronous check cost.

Key observations:

  • Pooled (ValueTask) and ProtoPromise: sub-10 ns combined signal + synchronous check
  • RefImpl and Nito: ~2× slower than Pooled
Description Mean Ratio Allocated
SetThenWait · AsyncAutoReset · ProtoPromise 3.628 ns 0.77 -
SetThenWait · AsyncAutoReset · Pooled (ValueTask) 4.714 ns 1.00 -
SetThenWait · AsyncAutoReset · Pooled (AsTask) 5.894 ns 1.25 -
SetThenWait · AsyncAutoReset · RefImpl 9.885 ns 2.10 -
SetThenWait · AsyncAutoReset · Nito.AsyncEx 10.082 ns 2.14 -

WaitThenSet

N waiters call WaitAsync, then Set() is called N times from another context. Each Set/Wait round trip involves a full async scheduling cycle (suspend + resume).

Key observations:

  • Pooled (AsValueTask) at 1 waiter: ~14% faster than default Pooled (ValueTask) when using the AsValueTask() overload
  • Pooled (AsValueTask SyncCont): synchronized continuation (inline resume) saves a context switch; similar result
  • At 100 waiters: Pooled (VT) ~25% faster than Windows for the ValueTask path
  • Nito at 100 waiters with NotCancelled: hundreds of microseconds — 100 per-waiter CancellationToken registrations dominate
Description Iterations cancellationType Mean Ratio Allocated
WaitThenSet · AsyncAutoReset · ProtoPromise 1 None 17.96 ns 0.84 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask SyncCont) 1 None 18.43 ns 0.86 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask) 1 None 18.49 ns 0.86 -
WaitThenSet · AsyncAutoReset · Pooled (ValueTask) 1 None 21.41 ns 1.00 -
WaitThenSet · AsyncAutoReset · Pooled (SyncCont) 1 None 21.58 ns 1.01 -
WaitThenSet · AsyncAutoReset · RefImpl 1 None 24.44 ns 1.14 96 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask SyncCont) 1 None 29.64 ns 1.38 80 B
WaitThenSet · AsyncAutoReset · Nito.AsyncEx 1 None 31.51 ns 1.47 160 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask) 1 None 1,230.34 ns 57.47 229 B
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask) 1 NotCancelled 29.64 ns 0.88 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask SyncCont) 1 NotCancelled 29.84 ns 0.89 -
WaitThenSet · AsyncAutoReset · ProtoPromise 1 NotCancelled 30.59 ns 0.91 -
WaitThenSet · AsyncAutoReset · Pooled (SyncCont) 1 NotCancelled 32.65 ns 0.97 -
WaitThenSet · AsyncAutoReset · Pooled (ValueTask) 1 NotCancelled 33.57 ns 1.00 -
WaitThenSet · AsyncAutoReset · Pooled (AsTask SyncCont) 1 NotCancelled 41.08 ns 1.22 80 B
WaitThenSet · AsyncAutoReset · Nito.AsyncEx 1 NotCancelled 628.48 ns 18.72 400 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask) 1 NotCancelled 1,369.58 ns 40.80 232 B
WaitThenSet · AsyncAutoReset · ProtoPromise 2 None 34.51 ns 0.71 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask SyncCont) 2 None 43.38 ns 0.89 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask) 2 None 45.39 ns 0.93 -
WaitThenSet · AsyncAutoReset · RefImpl 2 None 47.53 ns 0.97 192 B
WaitThenSet · AsyncAutoReset · Pooled (ValueTask) 2 None 48.84 ns 1.00 -
WaitThenSet · AsyncAutoReset · Pooled (SyncCont) 2 None 49.37 ns 1.01 -
WaitThenSet · AsyncAutoReset · Nito.AsyncEx 2 None 60.79 ns 1.24 320 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask SyncCont) 2 None 72.14 ns 1.48 160 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask) 2 None 1,814.28 ns 37.15 342 B
WaitThenSet · AsyncAutoReset · ProtoPromise 2 NotCancelled 61.65 ns 0.86 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask) 2 NotCancelled 67.33 ns 0.94 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask SyncCont) 2 NotCancelled 68.59 ns 0.95 -
WaitThenSet · AsyncAutoReset · Pooled (ValueTask) 2 NotCancelled 71.95 ns 1.00 -
WaitThenSet · AsyncAutoReset · Pooled (SyncCont) 2 NotCancelled 72.46 ns 1.01 -
WaitThenSet · AsyncAutoReset · Pooled (AsTask SyncCont) 2 NotCancelled 94.77 ns 1.32 160 B
WaitThenSet · AsyncAutoReset · Nito.AsyncEx 2 NotCancelled 1,071.33 ns 14.89 800 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask) 2 NotCancelled 1,935.44 ns 26.90 344 B
WaitThenSet · AsyncAutoReset · ProtoPromise 10 None 165.84 ns 0.64 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask SyncCont) 10 None 230.77 ns 0.89 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask) 10 None 235.56 ns 0.91 -
WaitThenSet · AsyncAutoReset · RefImpl 10 None 237.92 ns 0.92 960 B
WaitThenSet · AsyncAutoReset · Pooled (ValueTask) 10 None 258.24 ns 1.00 -
WaitThenSet · AsyncAutoReset · Pooled (SyncCont) 10 None 265.52 ns 1.03 -
WaitThenSet · AsyncAutoReset · Nito.AsyncEx 10 None 298.09 ns 1.15 1600 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask SyncCont) 10 None 364.88 ns 1.41 800 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask) 10 None 5,112.86 ns 19.80 1239 B
WaitThenSet · AsyncAutoReset · ProtoPromise 10 NotCancelled 313.55 ns 0.82 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask) 10 NotCancelled 348.47 ns 0.91 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask SyncCont) 10 NotCancelled 355.19 ns 0.93 -
WaitThenSet · AsyncAutoReset · Pooled (SyncCont) 10 NotCancelled 376.28 ns 0.99 -
WaitThenSet · AsyncAutoReset · Pooled (ValueTask) 10 NotCancelled 381.33 ns 1.00 -
WaitThenSet · AsyncAutoReset · Pooled (AsTask SyncCont) 10 NotCancelled 475.57 ns 1.25 800 B
WaitThenSet · AsyncAutoReset · Nito.AsyncEx 10 NotCancelled 5,104.58 ns 13.39 4000 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask) 10 NotCancelled 6,877.33 ns 18.04 1240 B
WaitThenSet · AsyncAutoReset · ProtoPromise 100 None 1,606.21 ns 0.64 -
WaitThenSet · AsyncAutoReset · RefImpl 100 None 2,147.13 ns 0.86 9600 B
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask) 100 None 2,157.25 ns 0.86 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask SyncCont) 100 None 2,184.42 ns 0.87 -
WaitThenSet · AsyncAutoReset · Pooled (ValueTask) 100 None 2,501.68 ns 1.00 -
WaitThenSet · AsyncAutoReset · Pooled (SyncCont) 100 None 2,519.45 ns 1.01 -
WaitThenSet · AsyncAutoReset · Nito.AsyncEx 100 None 2,873.12 ns 1.15 16000 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask SyncCont) 100 None 3,552.41 ns 1.42 8000 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask) 100 None 33,795.11 ns 13.51 11319 B
WaitThenSet · AsyncAutoReset · ProtoPromise 100 NotCancelled 3,062.41 ns 0.83 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask SyncCont) 100 NotCancelled 3,339.76 ns 0.91 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask) 100 NotCancelled 3,360.55 ns 0.91 -
WaitThenSet · AsyncAutoReset · Pooled (ValueTask) 100 NotCancelled 3,679.41 ns 1.00 -
WaitThenSet · AsyncAutoReset · Pooled (SyncCont) 100 NotCancelled 3,722.32 ns 1.01 -
WaitThenSet · AsyncAutoReset · Pooled (AsTask SyncCont) 100 NotCancelled 4,558.07 ns 1.24 8000 B
WaitThenSet · AsyncAutoReset · Nito.AsyncEx 100 NotCancelled 61,744.88 ns 16.78 40000 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask) 100 NotCancelled 112,610.58 ns 30.61 11326 B

AsyncManualResetEvent

AsyncManualResetEvent releases all waiters when set and stays set until explicitly reset. The SetReset benchmark measures the rapid set/reset cycle. SetThenWait measures a set followed by a synchronous wait (which completes immediately since the event is already set). WaitThenSet drives N concurrent waiters.

SetReset

Combined set-then-reset cycle — captures the cost of toggling the event state with no waiters.

Key observations:

  • Pooled: ~4× faster than ManualResetEventSlim.Set+Reset and ~65× faster than ManualResetEvent
  • ProtoPromise: fastest overall; ManualResetEvent (kernel): ~4× cheaper on macOS than Windows
Description Mean Ratio Allocated
SetReset · AsyncManualReset · ProtoPromise 1.009 ns 0.62 -
SetReset · AsyncManualReset · Pooled 1.616 ns 1.00 -
SetReset · ManualResetEventSlim · System 6.662 ns 4.12 -
SetReset · AsyncManualReset · RefImpl 9.369 ns 5.80 96 B
SetReset · AsyncManualReset · Nito.AsyncEx 15.199 ns 9.40 96 B
SetReset · ManualResetEvent · System 108.067 ns 66.87 -

SetThenWait

Description Mean Ratio Allocated
SetThenWait · AsyncManualReset · ProtoPromise 4.203 ns 0.65 -
SetThenWait · AsyncManualReset · Pooled (AsTask) 5.999 ns 0.92 -
SetThenWait · AsyncManualReset · Pooled (ValueTask) 6.505 ns 1.00 -
SetThenWait · AsyncManualReset · RefImpl 12.832 ns 1.97 96 B
SetThenWait · AsyncManualReset · Nito.AsyncEx 21.813 ns 3.35 96 B

WaitThenSet

Unlike AsyncAutoResetEvent, the AsyncManualResetEvent WaitThenSet benchmark releases all N waiters in a single Set() call (broadcast semantics). This means the allocation for RefImpl stays constant regardless of waiter count (single TaskCompletionSource shared by all).

Key observations:

  • Pooled (AsValueTask) at 1 waiter: ~15% faster than Windows
  • NotCancelled adds roughly 50–60% overhead per waiter at 1 iteration for the CancellationToken registration
  • Nito NotCancelled at 100 waiters: hundreds of microseconds — 100 per-waiter registrations dominate
Description Iterations cancellationType Mean Ratio Allocated
WaitThenSet · AsyncManualReset · RefImpl 1 None 16.47 ns 0.81 96 B
WaitThenSet · AsyncManualReset · Pooled (AsValueTask SyncCont) 1 None 17.19 ns 0.84 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask) 1 None 17.54 ns 0.86 -
WaitThenSet · AsyncManualReset · ProtoPromise 1 None 18.54 ns 0.91 -
WaitThenSet · AsyncManualReset · Pooled (ValueTask) 1 None 20.44 ns 1.00 -
WaitThenSet · AsyncManualReset · Pooled (SyncCont) 1 None 20.75 ns 1.02 -
WaitThenSet · AsyncManualReset · Nito.AsyncEx 1 None 26.62 ns 1.30 96 B
WaitThenSet · AsyncManualReset · Pooled (AsTask SyncCont) 1 None 28.74 ns 1.41 80 B
WaitThenSet · AsyncManualReset · Pooled (AsTask) 1 None 1,291.26 ns 63.19 230 B
WaitThenSet · AsyncManualReset · Pooled (AsValueTask SyncCont) 1 NotCancelled 28.78 ns 0.91 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask) 1 NotCancelled 29.50 ns 0.93 -
WaitThenSet · AsyncManualReset · ProtoPromise 1 NotCancelled 31.40 ns 0.99 -
WaitThenSet · AsyncManualReset · Pooled (SyncCont) 1 NotCancelled 31.65 ns 1.00 -
WaitThenSet · AsyncManualReset · Pooled (ValueTask) 1 NotCancelled 31.71 ns 1.00 -
WaitThenSet · AsyncManualReset · Pooled (AsTask SyncCont) 1 NotCancelled 41.95 ns 1.32 80 B
WaitThenSet · AsyncManualReset · Nito.AsyncEx 1 NotCancelled 1,443.13 ns 45.52 808 B
WaitThenSet · AsyncManualReset · Pooled (AsTask) 1 NotCancelled 1,496.60 ns 47.21 232 B
WaitThenSet · AsyncManualReset · RefImpl 2 None 20.27 ns 0.44 96 B
WaitThenSet · AsyncManualReset · ProtoPromise 2 None 33.62 ns 0.73 -
WaitThenSet · AsyncManualReset · Nito.AsyncEx 2 None 34.65 ns 0.76 96 B
WaitThenSet · AsyncManualReset · Pooled (AsValueTask SyncCont) 2 None 42.09 ns 0.92 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask) 2 None 43.47 ns 0.95 -
WaitThenSet · AsyncManualReset · Pooled (SyncCont) 2 None 43.78 ns 0.95 -
WaitThenSet · AsyncManualReset · Pooled (ValueTask) 2 None 45.88 ns 1.00 -
WaitThenSet · AsyncManualReset · Pooled (AsTask SyncCont) 2 None 65.24 ns 1.42 160 B
WaitThenSet · AsyncManualReset · Pooled (AsTask) 2 None 1,777.86 ns 38.76 343 B
WaitThenSet · AsyncManualReset · ProtoPromise 2 NotCancelled 62.17 ns 0.92 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask) 2 NotCancelled 65.48 ns 0.97 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask SyncCont) 2 NotCancelled 66.38 ns 0.98 -
WaitThenSet · AsyncManualReset · Pooled (ValueTask) 2 NotCancelled 67.42 ns 1.00 -
WaitThenSet · AsyncManualReset · Pooled (SyncCont) 2 NotCancelled 68.71 ns 1.02 -
WaitThenSet · AsyncManualReset · Pooled (AsTask SyncCont) 2 NotCancelled 103.73 ns 1.54 160 B
WaitThenSet · AsyncManualReset · Pooled (AsTask) 2 NotCancelled 2,228.65 ns 33.06 344 B
WaitThenSet · AsyncManualReset · Nito.AsyncEx 2 NotCancelled 2,316.48 ns 34.36 1488 B
WaitThenSet · AsyncManualReset · RefImpl 10 None 58.16 ns 0.23 96 B
WaitThenSet · AsyncManualReset · Nito.AsyncEx 10 None 100.26 ns 0.40 96 B
WaitThenSet · AsyncManualReset · ProtoPromise 10 None 159.08 ns 0.64 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask) 10 None 212.14 ns 0.85 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask SyncCont) 10 None 217.21 ns 0.87 -
WaitThenSet · AsyncManualReset · Pooled (ValueTask) 10 None 248.87 ns 1.00 -
WaitThenSet · AsyncManualReset · Pooled (SyncCont) 10 None 250.88 ns 1.01 -
WaitThenSet · AsyncManualReset · Pooled (AsTask SyncCont) 10 None 338.66 ns 1.36 800 B
WaitThenSet · AsyncManualReset · Pooled (AsTask) 10 None 6,269.22 ns 25.19 1240 B
WaitThenSet · AsyncManualReset · ProtoPromise 10 NotCancelled 303.05 ns 0.80 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask SyncCont) 10 NotCancelled 344.64 ns 0.91 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask) 10 NotCancelled 347.10 ns 0.92 -
WaitThenSet · AsyncManualReset · Pooled (SyncCont) 10 NotCancelled 376.76 ns 1.00 -
WaitThenSet · AsyncManualReset · Pooled (ValueTask) 10 NotCancelled 377.14 ns 1.00 -
WaitThenSet · AsyncManualReset · Pooled (AsTask SyncCont) 10 NotCancelled 477.58 ns 1.27 800 B
WaitThenSet · AsyncManualReset · Nito.AsyncEx 10 NotCancelled 6,880.06 ns 18.24 6464 B
WaitThenSet · AsyncManualReset · Pooled (AsTask) 10 NotCancelled 7,417.03 ns 19.67 1240 B
WaitThenSet · AsyncManualReset · RefImpl 100 None 460.79 ns 0.19 96 B
WaitThenSet · AsyncManualReset · Nito.AsyncEx 100 None 806.83 ns 0.33 96 B
WaitThenSet · AsyncManualReset · ProtoPromise 100 None 1,457.80 ns 0.60 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask SyncCont) 100 None 2,082.27 ns 0.86 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask) 100 None 2,088.38 ns 0.86 -
WaitThenSet · AsyncManualReset · Pooled (SyncCont) 100 None 2,413.12 ns 0.99 -
WaitThenSet · AsyncManualReset · Pooled (ValueTask) 100 None 2,428.53 ns 1.00 -
WaitThenSet · AsyncManualReset · Pooled (AsTask SyncCont) 100 None 3,272.00 ns 1.35 8000 B
WaitThenSet · AsyncManualReset · Pooled (AsTask) 100 None 32,830.61 ns 13.52 11320 B
WaitThenSet · AsyncManualReset · ProtoPromise 100 NotCancelled 2,838.95 ns 0.78 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask) 100 NotCancelled 3,284.09 ns 0.90 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask SyncCont) 100 NotCancelled 3,321.15 ns 0.91 -
WaitThenSet · AsyncManualReset · Pooled (SyncCont) 100 NotCancelled 3,575.24 ns 0.98 -
WaitThenSet · AsyncManualReset · Pooled (ValueTask) 100 NotCancelled 3,642.58 ns 1.00 -
WaitThenSet · AsyncManualReset · Pooled (AsTask SyncCont) 100 NotCancelled 4,450.96 ns 1.22 8000 B
WaitThenSet · AsyncManualReset · Pooled (AsTask) 100 NotCancelled 103,311.74 ns 28.36 11327 B
WaitThenSet · AsyncManualReset · Nito.AsyncEx 100 NotCancelled 150,459.74 ns 41.31 61615 B

AsyncSemaphore

AsyncSemaphore manages a counted resource permit. The single-permit benchmark measures the wait+release cycle uncontested (the permit is available, so WaitAsync takes the fast path).

Key observations:

  • Pooled: ~30% faster than Windows — the largest relative advantage across all uncontested benchmarks
  • ProtoPromise: ~25% faster than Pooled
  • System.SemaphoreSlim: ~2× slower than Pooled; ~25% cheaper than on Windows (lighter macOS kernel semaphore)
Description Mean Ratio Allocated
WaitRelease · AsyncSemaphore · ProtoPromise 4.945 ns 0.77 -
WaitRelease · AsyncSemaphore · Pooled 6.412 ns 1.00 -
WaitRelease · AsyncSemaphore · Nito.AsyncEx 11.604 ns 1.81 -
WaitRelease · AsyncSemaphore · RefImpl 11.697 ns 1.82 -
WaitRelease · SemaphoreSlim · System 12.635 ns 1.97 -

AsyncCountdownEvent

AsyncCountdownEvent completes when signaled N times. Two scenarios: SignalAndWait (last signal also unblocks the single waiter atomically), and WaitAndSignal (the waiter is already blocking when signals arrive).

Key observations:

  • Pooled (SignalAndWait, P=1): ~28% faster than Windows
  • System.CountdownEvent: near-identical on both platforms — kernel countdown objects normalize across architectures
  • At P=10, all implementations are within 2× of each other; Pooled matches System.CountdownEvent
Description ParticipantCount Mean Ratio Allocated
SignalAndWait · AsyncCountdownEv · ProtoPromise 1 4.295 ns 0.74 -
SignalAndWait · AsyncCountdownEv · Pooled 1 5.787 ns 1.00 -
SignalAndWait · CountdownEvent · System 1 6.401 ns 1.11 -
SignalAndWait · AsyncCountdownEv · RefImpl 1 13.402 ns 2.32 96 B
WaitAndSignal · AsyncCountdownEv · ProtoPromise 1 14.133 ns 2.44 -
WaitAndSignal · AsyncCountdownEv · Pooled 1 34.716 ns 6.00 -
SignalAndWait · AsyncCountdownEv · ProtoPromise 10 15.277 ns 0.69 -
SignalAndWait · CountdownEvent · System 10 16.036 ns 0.72 -
SignalAndWait · AsyncCountdownEv · RefImpl 10 21.003 ns 0.95 96 B
SignalAndWait · AsyncCountdownEv · Pooled 10 22.133 ns 1.00 -
WaitAndSignal · AsyncCountdownEv · ProtoPromise 10 22.524 ns 1.02 -
WaitAndSignal · AsyncCountdownEv · Pooled 10 45.687 ns 2.06 -

AsyncBarrier

AsyncBarrier blocks all N participants until all have signaled, then releases them simultaneously. The SignalAndWait benchmark measures the end-to-end barrier phase cycle.

Key observations:

  • Pooled at P=1: ~39% faster than Windows
  • System.Barrier at P=1: ~160× slower than Pooled; the ratio vs Pooled is much worse here than on Windows (~42×); System.Barrier performs full OS thread synchronization internally
  • At P=10: Pooled ~23% faster than Windows; System.Barrier ~2.8× cheaper than on Windows at P=10
Description ParticipantCount Mean Ratio Allocated
SignalAndWait · AsyncBarrier · Pooled 1 6.663 ns 1.00 -
SignalAndWait · Barrier · System 1 1,080.414 ns 162.15 239 B
SignalAndWait · AsyncBarrier · RefImpl 1 1,664.424 ns 249.80 8473 B
SignalAndWait · AsyncBarrier · Pooled 10 195.938 ns 1.00 -
SignalAndWait · AsyncBarrier · RefImpl 10 1,848.135 ns 9.43 8691 B
SignalAndWait · Barrier · System 10 14,392.134 ns 73.46 1392 B

AsyncReaderWriterLock

AsyncReaderWriterLock supports multiple concurrent readers or a single exclusive writer, plus an upgradeable reader that can atomically promote to writer. Benchmarks cover four access patterns:

  • WriterLock — exclusive write acquire+release (uncontested)
  • ReaderLock — shared read acquire+release at N concurrent readers
  • UpgradeableReaderLock — upgradeable acquire at N concurrent upgradeables
  • UpgradedWriterLock — upgrade from upgradeable to writer at N concurrent upgradeables

WriterLock (uncontested)

Key observations:

  • Pooled and ProtoPromise: near parity — fastest async writer lock on this platform
  • Both are ~34% faster than Windows for the Pooled path
  • System.ReaderWriterLockSlim: ~35% faster than Pooled (synchronous acquire path); ~33% faster than Windows equivalent
  • VS.Threading: async overhead ~215× vs Pooled due to its queuing model
Description Mean Ratio Allocated
WriterLock · RWLockSlim · System 4.605 ns 0.67 -
WriterLock · AsyncRWLock · Proto.Promises 6.874 ns 1.00 -
WriterLock · AsyncRWLock · Pooled 6.881 ns 1.00 -
WriterLock · AsyncRWLock · RefImpl 12.124 ns 1.76 -
WriterLock · AsyncRWLock · Nito.AsyncEx 58.594 ns 8.51 496 B
WriterLock · AsyncRWLock · VS.Threading 1,481.982 ns 215.36 584 B

ReaderLock

The reader lock benchmark reveals a notable contention inversion between platforms:

  • Uncontested (0 concurrent readers): M4 ~2× faster than Windows — the strongest single uncontested advantage across all threading benchmarks
  • 1 concurrent reader: Windows ~32% faster with a single contending reader; scheduling a resume on macOS ThreadPool costs more for the RWLock resumption path
  • 100 concurrent readers: Windows ~2× faster at high contention
  • ProtoPromise at 100 readers: macOS dramatically outperforms Windows (~0.13 vs 0.73 ratio to Pooled) — ProtoPromise's lock-free reader promotion is particularly effective at broadcast-style reader release on M4
Description Iterations cancellationType Mean Ratio Allocated
ReaderLock · RWLockSlim · System 0 None 6.172 ns 0.71 -
ReaderLock · AsyncRWLock · Pooled 0 None 8.639 ns 1.00 -
ReaderLock · AsyncRWLock · Proto.Promises 0 None 11.373 ns 1.32 -
ReaderLock · AsyncRWLock · RefImpl 0 None 13.955 ns 1.62 -
ReaderLock · AsyncRWLock · Nito.AsyncEx 0 None 42.188 ns 4.89 320 B
ReaderLock · AsyncRWLock · VS.Threading 0 None 169.288 ns 19.60 208 B
ReaderLock · AsyncRWLock · Pooled 0 NotCancelled 8.813 ns 1.00 -
ReaderLock · AsyncRWLock · Proto.Promises 0 NotCancelled 11.912 ns 1.35 -
ReaderLock · AsyncRWLock · Nito.AsyncEx 0 NotCancelled 41.956 ns 4.77 320 B
ReaderLock · AsyncRWLock · VS.Threading 0 NotCancelled 173.597 ns 19.72 208 B
ReaderLock · RWLockSlim · System 1 None 10.560 ns 0.23 -
ReaderLock · AsyncRWLock · Proto.Promises 1 None 16.098 ns 0.35 -
ReaderLock · AsyncRWLock · RefImpl 1 None 23.725 ns 0.52 -
ReaderLock · AsyncRWLock · Pooled 1 None 45.892 ns 1.00 -
ReaderLock · AsyncRWLock · Nito.AsyncEx 1 None 84.073 ns 1.83 640 B
ReaderLock · AsyncRWLock · VS.Threading 1 None 403.626 ns 8.80 416 B
ReaderLock · AsyncRWLock · Proto.Promises 1 NotCancelled 16.784 ns 0.37 -
ReaderLock · AsyncRWLock · Pooled 1 NotCancelled 45.025 ns 1.00 -
ReaderLock · AsyncRWLock · Nito.AsyncEx 1 NotCancelled 93.791 ns 2.08 640 B
ReaderLock · AsyncRWLock · VS.Threading 1 NotCancelled 405.231 ns 9.00 416 B
ReaderLock · RWLockSlim · System 10 None 53.209 ns 0.16 -
ReaderLock · AsyncRWLock · Proto.Promises 10 None 54.324 ns 0.16 -
ReaderLock · AsyncRWLock · RefImpl 10 None 114.815 ns 0.34 -
ReaderLock · AsyncRWLock · Pooled 10 None 341.559 ns 1.00 -
ReaderLock · AsyncRWLock · Nito.AsyncEx 10 None 480.115 ns 1.41 3520 B
ReaderLock · AsyncRWLock · VS.Threading 10 None 2,924.869 ns 8.56 2288 B
ReaderLock · AsyncRWLock · Proto.Promises 10 NotCancelled 54.705 ns 0.16 -
ReaderLock · AsyncRWLock · Pooled 10 NotCancelled 348.494 ns 1.00 -
ReaderLock · AsyncRWLock · Nito.AsyncEx 10 NotCancelled 466.506 ns 1.34 3520 B
ReaderLock · AsyncRWLock · VS.Threading 10 NotCancelled 2,913.725 ns 8.36 2288 B
ReaderLock · AsyncRWLock · Proto.Promises 100 None 452.161 ns 0.13 -
ReaderLock · RWLockSlim · System 100 None 489.782 ns 0.14 -
ReaderLock · AsyncRWLock · RefImpl 100 None 991.034 ns 0.29 -
ReaderLock · AsyncRWLock · Pooled 100 None 3,419.210 ns 1.00 -
ReaderLock · AsyncRWLock · Nito.AsyncEx 100 None 4,250.900 ns 1.24 32320 B
ReaderLock · AsyncRWLock · VS.Threading 100 None 73,780.822 ns 21.58 21008 B
ReaderLock · AsyncRWLock · Proto.Promises 100 NotCancelled 473.818 ns 0.14 -
ReaderLock · AsyncRWLock · Pooled 100 NotCancelled 3,412.131 ns 1.00 -
ReaderLock · AsyncRWLock · Nito.AsyncEx 100 NotCancelled 4,264.565 ns 1.25 32320 B
ReaderLock · AsyncRWLock · VS.Threading 100 NotCancelled 73,570.658 ns 21.56 21008 B

UpgradeableReaderLock

Same contention inversion pattern as reader lock:

  • Uncontested: M4 ~2× faster than Windows
  • System.ReaderWriterLockSlim upgradeable: ~40% faster than Pooled uncontested; ~30% cheaper than on Windows
  • VS.Threading upgradeable: ~1.4× slower than Windows uncontested due to lock-free upgradeable state tracking differences; allocates 616 B per acquire
Description Iterations cancellationType Mean Ratio Allocated
UpgradeableReaderLock · RWLockSlim · System 0 None 4.970 ns 0.59 -
UpgradeableReaderLock · AsyncRWLock · Pooled 0 None 8.437 ns 1.00 -
UpgradeableReaderLock · AsyncRWLock · Proto.Promises 0 None 12.288 ns 1.46 -
UpgradeableReaderLock · AsyncRWLock · VS.Threading 0 None 1,509.803 ns 178.98 616 B
UpgradeableReaderLock · AsyncRWLock · Pooled 0 NotCancelled 8.484 ns 1.00 -
UpgradeableReaderLock · AsyncRWLock · Proto.Promises 0 NotCancelled 12.314 ns 1.45 -
UpgradeableReaderLock · AsyncRWLock · VS.Threading 0 NotCancelled 1,552.237 ns 182.97 616 B
UpgradeableReaderLock · RWLockSlim · System 1 None 4.977 ns 0.14 -
UpgradeableReaderLock · AsyncRWLock · Proto.Promises 1 None 11.034 ns 0.30 -
UpgradeableReaderLock · AsyncRWLock · Pooled 1 None 36.772 ns 1.00 -
UpgradeableReaderLock · AsyncRWLock · VS.Threading 1 None 1,431.211 ns 38.93 616 B
UpgradeableReaderLock · AsyncRWLock · Proto.Promises 1 NotCancelled 11.031 ns 0.30 -
UpgradeableReaderLock · AsyncRWLock · Pooled 1 NotCancelled 36.280 ns 1.00 -
UpgradeableReaderLock · AsyncRWLock · VS.Threading 1 NotCancelled 1,497.189 ns 41.27 616 B
UpgradeableReaderLock · RWLockSlim · System 2 None 4.963 ns 0.14 -
UpgradeableReaderLock · AsyncRWLock · Proto.Promises 2 None 11.068 ns 0.30 -
UpgradeableReaderLock · AsyncRWLock · Pooled 2 None 36.723 ns 1.00 -
UpgradeableReaderLock · AsyncRWLock · VS.Threading 2 None 1,524.603 ns 41.52 616 B
UpgradeableReaderLock · AsyncRWLock · Proto.Promises 2 NotCancelled 11.024 ns 0.30 -
UpgradeableReaderLock · AsyncRWLock · Pooled 2 NotCancelled 36.582 ns 1.00 -
UpgradeableReaderLock · AsyncRWLock · VS.Threading 2 NotCancelled 1,537.993 ns 42.04 616 B
UpgradeableReaderLock · RWLockSlim · System 5 None 19.204 ns 0.14 -
UpgradeableReaderLock · AsyncRWLock · Proto.Promises 5 None 22.802 ns 0.17 -
UpgradeableReaderLock · AsyncRWLock · Pooled 5 None 136.771 ns 1.00 -
UpgradeableReaderLock · AsyncRWLock · VS.Threading 5 None 2,051.705 ns 15.00 1240 B
UpgradeableReaderLock · AsyncRWLock · Proto.Promises 5 NotCancelled 23.691 ns 0.17 -
UpgradeableReaderLock · AsyncRWLock · Pooled 5 NotCancelled 135.748 ns 1.00 -
UpgradeableReaderLock · AsyncRWLock · VS.Threading 5 NotCancelled 2,151.423 ns 15.85 1240 B

UpgradedWriterLock

The upgraded writer lock holds an upgradeable reader then atomically promotes to exclusive writer, requiring all active readers to drain first.

  • Uncontested: M4 ~32% faster than Windows
  • 1 concurrent upgraded writer: Windows ~30% faster (same inversion as reader lock)
  • 5 concurrent upgraded writers: Windows ~2.5× faster — writer upgrade queuing is the scenario where Windows ThreadPool's Task scheduling advantage is most visible
Description Iterations cancellationType Mean Ratio Allocated
UpgradedWriterLock · RWLockSlim · System 0 None 10.34 ns 0.67 -
UpgradedWriterLock · AsyncRWLock · Pooled 0 None 15.45 ns 1.00 -
UpgradedWriterLock · AsyncRWLock · Proto.Promises 0 None 21.60 ns 1.40 -
UpgradedWriterLock · AsyncRWLock · VS.Threading 0 None 1,601.02 ns 103.64 824 B
UpgradedWriterLock · AsyncRWLock · Pooled 0 NotCancelled 15.31 ns 1.00 -
UpgradedWriterLock · AsyncRWLock · Proto.Promises 0 NotCancelled 18.73 ns 1.22 -
UpgradedWriterLock · AsyncRWLock · VS.Threading 0 NotCancelled 1,580.17 ns 103.18 824 B
UpgradedWriterLock · RWLockSlim · System 1 None 16.29 ns 0.23 -
UpgradedWriterLock · AsyncRWLock · Proto.Promises 1 None 31.34 ns 0.45 -
UpgradedWriterLock · AsyncRWLock · Pooled 1 None 70.25 ns 1.00 -
UpgradedWriterLock · AsyncRWLock · VS.Threading 1 None 1,865.61 ns 26.56 1032 B
UpgradedWriterLock · AsyncRWLock · Proto.Promises 1 NotCancelled 42.41 ns 0.60 -
UpgradedWriterLock · AsyncRWLock · Pooled 1 NotCancelled 70.82 ns 1.00 -
UpgradedWriterLock · AsyncRWLock · VS.Threading 1 NotCancelled 1,903.70 ns 26.89 1032 B
UpgradedWriterLock · RWLockSlim · System 2 None 20.74 ns 0.17 -
UpgradedWriterLock · AsyncRWLock · Proto.Promises 2 None 35.07 ns 0.28 -
UpgradedWriterLock · AsyncRWLock · Pooled 2 None 125.18 ns 1.00 -
UpgradedWriterLock · AsyncRWLock · VS.Threading 2 None 2,172.35 ns 17.36 1240 B
UpgradedWriterLock · AsyncRWLock · Proto.Promises 2 NotCancelled 46.73 ns 0.36 -
UpgradedWriterLock · AsyncRWLock · Pooled 2 NotCancelled 128.91 ns 1.00 -
UpgradedWriterLock · AsyncRWLock · VS.Threading 2 NotCancelled 2,287.06 ns 17.74 1240 B
UpgradedWriterLock · RWLockSlim · System 5 None 33.92 ns 0.11 -
UpgradedWriterLock · AsyncRWLock · Proto.Promises 5 None 46.46 ns 0.15 -
UpgradedWriterLock · AsyncRWLock · Pooled 5 None 305.75 ns 1.00 -
UpgradedWriterLock · AsyncRWLock · VS.Threading 5 None 3,287.80 ns 10.75 1864 B
UpgradedWriterLock · AsyncRWLock · Proto.Promises 5 NotCancelled 58.86 ns 0.19 -
UpgradedWriterLock · AsyncRWLock · Pooled 5 NotCancelled 312.35 ns 1.00 -
UpgradedWriterLock · AsyncRWLock · VS.Threading 5 NotCancelled 3,500.68 ns 11.21 1864 B