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.4.1 (25E253) [Darwin 25.4.0]
Apple M4, 1 CPU, 10 logical and 10 physical cores
.NET SDK 10.0.301
[Host]    : .NET 10.0.9 (10.0.9, 10.0.926.27113), Arm64 RyuJIT armv8.0-a
.NET 10.0 : .NET 10.0.9 (10.0.9, 10.0.926.27113), 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.4601 ns 0.067 -
Lock · Interlocked.Inc · System 0.4692 ns 0.068 -
Lock · Interlocked.Add · System 0.4771 ns 0.069 -
Lock · Lock · System 1.7588 ns 0.255 -
Lock · Lock.EnterScope · System 1.7817 ns 0.258 -
Lock · Interlocked.CmpX · System 2.4232 ns 0.351 -
SpinLock · SpinLock · CryptoHives 2.6420 ns 0.382 -
Lock · lock() · System 2.9387 ns 0.425 -
LockAsync · AsyncLock · ProtoPromise 6.6327 ns 0.960 -
LockAsync · AsyncLock · Pooled 6.9102 ns 1.000 -
LockAsync · AsyncSemaphore · VS.Threading 11.4114 ns 1.651 -
LockAsync · AsyncLock · RefImpl 11.7925 ns 1.707 -
LockAsync · SemaphoreSlim · System 12.4404 ns 1.800 -
LockAsync · AsyncLock · NonKeyed 16.8037 ns 2.432 -
LockAsync · AsyncLock · Nito.AsyncEx 40.1211 ns 5.806 320 B
SpinWait · SpinOnce · System 44.1741 ns 6.393 -
SpinLock · SpinLock · System 52.1762 ns 7.551 -
LockAsync · AsyncLock · NeoSmart 60.4453 ns 8.748 208 B

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 8.425 ns 1.00 -
Multiple · AsyncLock · ProtoPromise 0 None 9.284 ns 1.10 -
Multiple · AsyncLock · Pooled (Task) 0 None 10.440 ns 1.24 -
Multiple · AsyncSemaphore · VS.Threading 0 None 12.675 ns 1.50 -
Multiple · AsyncLock · RefImpl 0 None 13.141 ns 1.56 -
Multiple · SemaphoreSlim · System 0 None 14.235 ns 1.69 -
Multiple · AsyncLock · NonKeyed 0 None 18.142 ns 2.15 -
Multiple · AsyncLock · Nito 0 None 41.584 ns 4.94 320 B
Multiple · AsyncLock · NeoSmart 0 None 50.834 ns 6.03 208 B
Multiple · AsyncLock · Pooled (ValueTask) 0 NotCancelled 8.514 ns 1.00 -
Multiple · AsyncLock · ProtoPromise 0 NotCancelled 9.266 ns 1.09 -
Multiple · AsyncLock · Pooled (Task) 0 NotCancelled 10.493 ns 1.23 -
Multiple · AsyncSemaphore · VS.Threading 0 NotCancelled 12.882 ns 1.51 -
Multiple · SemaphoreSlim · System 0 NotCancelled 14.293 ns 1.68 -
Multiple · AsyncLock · NonKeyed 0 NotCancelled 18.182 ns 2.14 -
Multiple · AsyncLock · Nito 0 NotCancelled 41.084 ns 4.83 320 B
Multiple · AsyncLock · NeoSmart 0 NotCancelled 51.570 ns 6.06 208 B
Multiple · AsyncLock · Pooled (ValueTask) 1 None 25.441 ns 1.00 -
Multiple · AsyncLock · ProtoPromise 1 None 27.270 ns 1.07 -
Multiple · SemaphoreSlim · System 1 None 36.967 ns 1.45 88 B
Multiple · AsyncSemaphore · VS.Threading 1 None 52.469 ns 2.06 168 B
Multiple · AsyncLock · RefImpl 1 None 65.429 ns 2.57 216 B
Multiple · AsyncLock · Nito 1 None 94.398 ns 3.71 728 B
Multiple · AsyncLock · NeoSmart 1 None 104.984 ns 4.13 416 B
Multiple · AsyncLock · NonKeyed 1 None 1,274.175 ns 50.09 351 B
Multiple · AsyncLock · Pooled (Task) 1 None 1,452.753 ns 57.10 271 B
Multiple · AsyncLock · Pooled (ValueTask) 1 NotCancelled 38.623 ns 1.00 -
Multiple · AsyncLock · ProtoPromise 1 NotCancelled 42.165 ns 1.09 -
Multiple · AsyncSemaphore · VS.Threading 1 NotCancelled 62.016 ns 1.61 168 B
Multiple · AsyncLock · NeoSmart 1 NotCancelled 108.661 ns 2.81 416 B
Multiple · AsyncLock · Nito 1 NotCancelled 649.216 ns 16.81 968 B
Multiple · SemaphoreSlim · System 1 NotCancelled 1,424.487 ns 36.88 504 B
Multiple · AsyncLock · Pooled (Task) 1 NotCancelled 1,465.472 ns 37.94 272 B
Multiple · AsyncLock · NonKeyed 1 NotCancelled 1,480.866 ns 38.34 640 B
Multiple · AsyncLock · ProtoPromise 10 None 194.709 ns 0.72 -
Multiple · SemaphoreSlim · System 10 None 245.409 ns 0.91 880 B
Multiple · AsyncLock · Pooled (ValueTask) 10 None 270.181 ns 1.00 -
Multiple · AsyncSemaphore · VS.Threading 10 None 453.778 ns 1.68 1680 B
Multiple · AsyncLock · RefImpl 10 None 556.398 ns 2.06 2160 B
Multiple · AsyncLock · NeoSmart 10 None 559.989 ns 2.07 2288 B
Multiple · AsyncLock · Nito 10 None 562.881 ns 2.08 4400 B
Multiple · AsyncLock · NonKeyed 10 None 7,555.876 ns 27.97 2296 B
Multiple · AsyncLock · Pooled (Task) 10 None 8,143.090 ns 30.14 1352 B
Multiple · AsyncLock · ProtoPromise 10 NotCancelled 334.922 ns 0.86 -
Multiple · AsyncLock · Pooled (ValueTask) 10 NotCancelled 389.866 ns 1.00 -
Multiple · AsyncSemaphore · VS.Threading 10 NotCancelled 551.252 ns 1.41 1680 B
Multiple · AsyncLock · NeoSmart 10 NotCancelled 563.921 ns 1.45 2288 B
Multiple · AsyncLock · Nito 10 NotCancelled 4,833.723 ns 12.40 6800 B
Multiple · AsyncLock · Pooled (Task) 10 NotCancelled 8,736.692 ns 22.41 1352 B
Multiple · SemaphoreSlim · System 10 NotCancelled 10,615.816 ns 27.23 3888 B
Multiple · AsyncLock · NonKeyed 10 NotCancelled 10,925.889 ns 28.02 5176 B
Multiple · AsyncLock · ProtoPromise 100 None 1,807.087 ns 0.78 -
Multiple · SemaphoreSlim · System 100 None 2,229.703 ns 0.96 8800 B
Multiple · AsyncLock · Pooled (ValueTask) 100 None 2,324.326 ns 1.00 -
Multiple · AsyncSemaphore · VS.Threading 100 None 4,462.744 ns 1.92 21120 B
Multiple · AsyncLock · NeoSmart 100 None 4,946.453 ns 2.13 21008 B
Multiple · AsyncLock · Nito 100 None 5,257.998 ns 2.26 41120 B
Multiple · AsyncLock · RefImpl 100 None 5,321.844 ns 2.29 21600 B
Multiple · AsyncLock · NonKeyed 100 None 50,706.763 ns 21.82 21739 B
Multiple · AsyncLock · Pooled (Task) 100 None 52,025.798 ns 22.38 12155 B
Multiple · AsyncLock · ProtoPromise 100 NotCancelled 3,207.920 ns 0.88 -
Multiple · AsyncLock · Pooled (ValueTask) 100 NotCancelled 3,639.009 ns 1.00 -
Multiple · AsyncLock · NeoSmart 100 NotCancelled 4,930.770 ns 1.36 21008 B
Multiple · AsyncSemaphore · VS.Threading 100 NotCancelled 5,529.917 ns 1.52 21120 B
Multiple · AsyncLock · Nito 100 NotCancelled 59,235.902 ns 16.28 65120 B
Multiple · AsyncLock · Pooled (Task) 100 NotCancelled 60,318.879 ns 16.58 12190 B
Multiple · SemaphoreSlim · System 100 NotCancelled 83,624.877 ns 22.98 37738 B
Multiple · AsyncLock · NonKeyed 100 NotCancelled 94,018.415 ns 25.84 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 · Pooled 0.4561 ns 1.00 -
Set · AsyncAutoReset · ProtoPromise 0.5768 ns 1.26 -
Set · AsyncAutoReset · RefImpl 2.9920 ns 6.56 -
Set · AsyncAutoReset · Nito.AsyncEx 3.2573 ns 7.14 -
Set · AutoResetEvent · System 55.2256 ns 121.09 -

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.590 ns 0.77 -
SetThenWait · AsyncAutoReset · Pooled (ValueTask) 4.632 ns 1.00 -
SetThenWait · AsyncAutoReset · Pooled (AsTask) 5.578 ns 1.20 -
SetThenWait · AsyncAutoReset · Nito.AsyncEx 9.310 ns 2.01 -
SetThenWait · AsyncAutoReset · RefImpl 9.921 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 18.04 ns 0.81 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask SyncCont) 1 None 19.83 ns 0.89 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask) 1 None 20.61 ns 0.92 -
WaitThenSet · AsyncAutoReset · Pooled (ValueTask) 1 None 22.35 ns 1.00 -
WaitThenSet · AsyncAutoReset · Pooled (SyncCont) 1 None 22.66 ns 1.01 -
WaitThenSet · AsyncAutoReset · RefImpl 1 None 24.99 ns 1.12 96 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask SyncCont) 1 None 31.33 ns 1.40 80 B
WaitThenSet · AsyncAutoReset · Nito.AsyncEx 1 None 31.88 ns 1.43 160 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask) 1 None 1,168.48 ns 52.28 230 B
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask) 1 NotCancelled 29.92 ns 0.89 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask SyncCont) 1 NotCancelled 30.96 ns 0.93 -
WaitThenSet · AsyncAutoReset · ProtoPromise 1 NotCancelled 31.23 ns 0.93 -
WaitThenSet · AsyncAutoReset · Pooled (ValueTask) 1 NotCancelled 33.47 ns 1.00 -
WaitThenSet · AsyncAutoReset · Pooled (SyncCont) 1 NotCancelled 33.66 ns 1.01 -
WaitThenSet · AsyncAutoReset · Pooled (AsTask SyncCont) 1 NotCancelled 43.40 ns 1.30 80 B
WaitThenSet · AsyncAutoReset · Nito.AsyncEx 1 NotCancelled 678.27 ns 20.27 400 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask) 1 NotCancelled 1,338.75 ns 40.01 232 B
WaitThenSet · AsyncAutoReset · ProtoPromise 2 None 34.21 ns 0.59 -
WaitThenSet · AsyncAutoReset · RefImpl 2 None 47.47 ns 0.82 192 B
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask SyncCont) 2 None 51.41 ns 0.89 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask) 2 None 52.59 ns 0.91 -
WaitThenSet · AsyncAutoReset · Pooled (SyncCont) 2 None 56.66 ns 0.98 -
WaitThenSet · AsyncAutoReset · Pooled (ValueTask) 2 None 57.91 ns 1.00 -
WaitThenSet · AsyncAutoReset · Nito.AsyncEx 2 None 60.65 ns 1.05 320 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask SyncCont) 2 None 73.16 ns 1.26 160 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask) 2 None 1,733.49 ns 29.94 342 B
WaitThenSet · AsyncAutoReset · ProtoPromise 2 NotCancelled 63.36 ns 0.85 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask SyncCont) 2 NotCancelled 69.03 ns 0.93 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask) 2 NotCancelled 70.77 ns 0.95 -
WaitThenSet · AsyncAutoReset · Pooled (ValueTask) 2 NotCancelled 74.56 ns 1.00 -
WaitThenSet · AsyncAutoReset · Pooled (SyncCont) 2 NotCancelled 75.09 ns 1.01 -
WaitThenSet · AsyncAutoReset · Pooled (AsTask SyncCont) 2 NotCancelled 98.72 ns 1.32 160 B
WaitThenSet · AsyncAutoReset · Nito.AsyncEx 2 NotCancelled 1,071.75 ns 14.38 800 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask) 2 NotCancelled 1,962.88 ns 26.33 344 B
WaitThenSet · AsyncAutoReset · ProtoPromise 10 None 165.33 ns 0.57 -
WaitThenSet · AsyncAutoReset · RefImpl 10 None 231.48 ns 0.80 960 B
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask) 10 None 264.91 ns 0.91 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask SyncCont) 10 None 267.93 ns 0.92 -
WaitThenSet · AsyncAutoReset · Pooled (ValueTask) 10 None 291.13 ns 1.00 -
WaitThenSet · AsyncAutoReset · Pooled (SyncCont) 10 None 297.34 ns 1.02 -
WaitThenSet · AsyncAutoReset · Nito.AsyncEx 10 None 298.07 ns 1.02 1600 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask SyncCont) 10 None 387.58 ns 1.33 800 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask) 10 None 6,006.54 ns 20.63 1239 B
WaitThenSet · AsyncAutoReset · ProtoPromise 10 NotCancelled 312.24 ns 0.78 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask) 10 NotCancelled 373.70 ns 0.93 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask SyncCont) 10 NotCancelled 377.26 ns 0.94 -
WaitThenSet · AsyncAutoReset · Pooled (SyncCont) 10 NotCancelled 394.53 ns 0.98 -
WaitThenSet · AsyncAutoReset · Pooled (ValueTask) 10 NotCancelled 401.78 ns 1.00 -
WaitThenSet · AsyncAutoReset · Pooled (AsTask SyncCont) 10 NotCancelled 509.86 ns 1.27 800 B
WaitThenSet · AsyncAutoReset · Nito.AsyncEx 10 NotCancelled 5,167.63 ns 12.86 4000 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask) 10 NotCancelled 7,401.84 ns 18.42 1240 B
WaitThenSet · AsyncAutoReset · ProtoPromise 100 None 1,604.52 ns 0.58 -
WaitThenSet · AsyncAutoReset · RefImpl 100 None 2,153.78 ns 0.79 9600 B
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask) 100 None 2,358.28 ns 0.86 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask SyncCont) 100 None 2,405.40 ns 0.88 -
WaitThenSet · AsyncAutoReset · Pooled (SyncCont) 100 None 2,713.10 ns 0.99 -
WaitThenSet · AsyncAutoReset · Pooled (ValueTask) 100 None 2,742.91 ns 1.00 -
WaitThenSet · AsyncAutoReset · Nito.AsyncEx 100 None 2,919.10 ns 1.06 16000 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask SyncCont) 100 None 3,604.36 ns 1.31 8000 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask) 100 None 34,738.25 ns 12.66 11319 B
WaitThenSet · AsyncAutoReset · ProtoPromise 100 NotCancelled 3,082.76 ns 0.81 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask) 100 NotCancelled 3,488.57 ns 0.91 -
WaitThenSet · AsyncAutoReset · Pooled (AsValueTask SyncCont) 100 NotCancelled 3,516.90 ns 0.92 -
WaitThenSet · AsyncAutoReset · Pooled (ValueTask) 100 NotCancelled 3,827.37 ns 1.00 -
WaitThenSet · AsyncAutoReset · Pooled (SyncCont) 100 NotCancelled 3,862.02 ns 1.01 -
WaitThenSet · AsyncAutoReset · Pooled (AsTask SyncCont) 100 NotCancelled 4,699.28 ns 1.23 8000 B
WaitThenSet · AsyncAutoReset · Nito.AsyncEx 100 NotCancelled 55,269.09 ns 14.44 40000 B
WaitThenSet · AsyncAutoReset · Pooled (AsTask) 100 NotCancelled 159,550.73 ns 41.69 11330 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 0.9164 ns 0.60 -
SetReset · AsyncManualReset · Pooled 1.5384 ns 1.00 -
SetReset · ManualResetEventSlim · System 6.8272 ns 4.44 -
SetReset · AsyncManualReset · RefImpl 9.2011 ns 5.98 96 B
SetReset · AsyncManualReset · Nito.AsyncEx 14.8942 ns 9.68 96 B
SetReset · ManualResetEvent · System 112.0806 ns 72.86 -

SetThenWait

Description Mean Ratio Allocated
SetThenWait · AsyncManualReset · ProtoPromise 4.114 ns 0.72 -
SetThenWait · AsyncManualReset · Pooled (AsTask) 5.260 ns 0.93 -
SetThenWait · AsyncManualReset · Pooled (ValueTask) 5.684 ns 1.00 -
SetThenWait · AsyncManualReset · RefImpl 12.428 ns 2.19 96 B
SetThenWait · AsyncManualReset · Nito.AsyncEx 21.419 ns 3.77 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.18 ns 0.73 96 B
WaitThenSet · AsyncManualReset · ProtoPromise 1 None 18.27 ns 0.83 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask SyncCont) 1 None 20.78 ns 0.94 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask) 1 None 21.81 ns 0.99 -
WaitThenSet · AsyncManualReset · Pooled (ValueTask) 1 None 22.09 ns 1.00 -
WaitThenSet · AsyncManualReset · Pooled (SyncCont) 1 None 23.22 ns 1.05 -
WaitThenSet · AsyncManualReset · Nito.AsyncEx 1 None 25.92 ns 1.17 96 B
WaitThenSet · AsyncManualReset · Pooled (AsTask SyncCont) 1 None 31.37 ns 1.42 80 B
WaitThenSet · AsyncManualReset · Pooled (AsTask) 1 None 1,227.92 ns 55.60 231 B
WaitThenSet · AsyncManualReset · Pooled (AsValueTask) 1 NotCancelled 29.69 ns 0.88 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask SyncCont) 1 NotCancelled 31.02 ns 0.92 -
WaitThenSet · AsyncManualReset · ProtoPromise 1 NotCancelled 32.12 ns 0.95 -
WaitThenSet · AsyncManualReset · Pooled (SyncCont) 1 NotCancelled 33.48 ns 0.99 -
WaitThenSet · AsyncManualReset · Pooled (ValueTask) 1 NotCancelled 33.76 ns 1.00 -
WaitThenSet · AsyncManualReset · Pooled (AsTask SyncCont) 1 NotCancelled 43.49 ns 1.29 80 B
WaitThenSet · AsyncManualReset · Pooled (AsTask) 1 NotCancelled 1,346.74 ns 39.89 232 B
WaitThenSet · AsyncManualReset · Nito.AsyncEx 1 NotCancelled 1,425.12 ns 42.21 808 B
WaitThenSet · AsyncManualReset · RefImpl 2 None 20.50 ns 0.36 96 B
WaitThenSet · AsyncManualReset · ProtoPromise 2 None 33.28 ns 0.59 -
WaitThenSet · AsyncManualReset · Nito.AsyncEx 2 None 35.64 ns 0.63 96 B
WaitThenSet · AsyncManualReset · Pooled (AsValueTask SyncCont) 2 None 48.81 ns 0.86 -
WaitThenSet · AsyncManualReset · Pooled (SyncCont) 2 None 55.93 ns 0.98 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask) 2 None 56.42 ns 0.99 -
WaitThenSet · AsyncManualReset · Pooled (ValueTask) 2 None 56.80 ns 1.00 -
WaitThenSet · AsyncManualReset · Pooled (AsTask SyncCont) 2 None 71.25 ns 1.25 160 B
WaitThenSet · AsyncManualReset · Pooled (AsTask) 2 None 1,875.99 ns 33.03 344 B
WaitThenSet · AsyncManualReset · ProtoPromise 2 NotCancelled 63.15 ns 0.88 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask) 2 NotCancelled 68.56 ns 0.96 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask SyncCont) 2 NotCancelled 68.65 ns 0.96 -
WaitThenSet · AsyncManualReset · Pooled (SyncCont) 2 NotCancelled 71.49 ns 1.00 -
WaitThenSet · AsyncManualReset · Pooled (ValueTask) 2 NotCancelled 71.53 ns 1.00 -
WaitThenSet · AsyncManualReset · Pooled (AsTask SyncCont) 2 NotCancelled 95.36 ns 1.33 160 B
WaitThenSet · AsyncManualReset · Pooled (AsTask) 2 NotCancelled 2,046.09 ns 28.60 344 B
WaitThenSet · AsyncManualReset · Nito.AsyncEx 2 NotCancelled 2,311.93 ns 32.32 1488 B
WaitThenSet · AsyncManualReset · RefImpl 10 None 57.53 ns 0.20 96 B
WaitThenSet · AsyncManualReset · Nito.AsyncEx 10 None 99.67 ns 0.34 96 B
WaitThenSet · AsyncManualReset · ProtoPromise 10 None 157.39 ns 0.54 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask SyncCont) 10 None 258.76 ns 0.89 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask) 10 None 259.12 ns 0.89 -
WaitThenSet · AsyncManualReset · Pooled (ValueTask) 10 None 291.94 ns 1.00 -
WaitThenSet · AsyncManualReset · Pooled (SyncCont) 10 None 325.39 ns 1.11 -
WaitThenSet · AsyncManualReset · Pooled (AsTask SyncCont) 10 None 383.58 ns 1.31 800 B
WaitThenSet · AsyncManualReset · Pooled (AsTask) 10 None 5,473.62 ns 18.75 1240 B
WaitThenSet · AsyncManualReset · ProtoPromise 10 NotCancelled 299.56 ns 0.77 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask) 10 NotCancelled 368.54 ns 0.95 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask SyncCont) 10 NotCancelled 371.09 ns 0.95 -
WaitThenSet · AsyncManualReset · Pooled (ValueTask) 10 NotCancelled 389.45 ns 1.00 -
WaitThenSet · AsyncManualReset · Pooled (SyncCont) 10 NotCancelled 394.69 ns 1.01 -
WaitThenSet · AsyncManualReset · Pooled (AsTask SyncCont) 10 NotCancelled 504.84 ns 1.30 800 B
WaitThenSet · AsyncManualReset · Pooled (AsTask) 10 NotCancelled 7,428.64 ns 19.07 1240 B
WaitThenSet · AsyncManualReset · Nito.AsyncEx 10 NotCancelled 7,450.48 ns 19.13 6464 B
WaitThenSet · AsyncManualReset · RefImpl 100 None 451.90 ns 0.16 96 B
WaitThenSet · AsyncManualReset · Nito.AsyncEx 100 None 921.42 ns 0.33 96 B
WaitThenSet · AsyncManualReset · ProtoPromise 100 None 1,445.45 ns 0.52 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask SyncCont) 100 None 2,404.66 ns 0.87 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask) 100 None 2,415.38 ns 0.87 -
WaitThenSet · AsyncManualReset · Pooled (SyncCont) 100 None 2,611.25 ns 0.94 -
WaitThenSet · AsyncManualReset · Pooled (ValueTask) 100 None 2,766.80 ns 1.00 -
WaitThenSet · AsyncManualReset · Pooled (AsTask SyncCont) 100 None 3,496.55 ns 1.26 8000 B
WaitThenSet · AsyncManualReset · Pooled (AsTask) 100 None 31,479.01 ns 11.38 11320 B
WaitThenSet · AsyncManualReset · ProtoPromise 100 NotCancelled 2,860.88 ns 0.77 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask SyncCont) 100 NotCancelled 3,445.33 ns 0.93 -
WaitThenSet · AsyncManualReset · Pooled (AsValueTask) 100 NotCancelled 3,482.04 ns 0.94 -
WaitThenSet · AsyncManualReset · Pooled (ValueTask) 100 NotCancelled 3,710.89 ns 1.00 -
WaitThenSet · AsyncManualReset · Pooled (SyncCont) 100 NotCancelled 3,816.98 ns 1.03 -
WaitThenSet · AsyncManualReset · Pooled (AsTask SyncCont) 100 NotCancelled 4,672.33 ns 1.26 8000 B
WaitThenSet · AsyncManualReset · Pooled (AsTask) 100 NotCancelled 99,611.44 ns 26.84 11325 B
WaitThenSet · AsyncManualReset · Nito.AsyncEx 100 NotCancelled 151,291.92 ns 40.77 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.777 ns 0.77 -
WaitRelease · AsyncSemaphore · Pooled 6.203 ns 1.00 -
WaitRelease · AsyncSemaphore · RefImpl 11.378 ns 1.83 -
WaitRelease · AsyncSemaphore · Nito.AsyncEx 11.417 ns 1.84 -
WaitRelease · SemaphoreSlim · System 12.665 ns 2.04 -

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.281 ns 0.77 -
SignalAndWait · AsyncCountdownEv · Pooled 1 5.573 ns 1.00 -
SignalAndWait · CountdownEvent · System 1 6.662 ns 1.20 -
SignalAndWait · AsyncCountdownEv · RefImpl 1 13.377 ns 2.40 96 B
WaitAndSignal · AsyncCountdownEv · ProtoPromise 1 13.752 ns 2.47 -
WaitAndSignal · AsyncCountdownEv · Pooled 1 35.327 ns 6.34 -
SignalAndWait · AsyncCountdownEv · ProtoPromise 10 15.227 ns 0.70 -
SignalAndWait · CountdownEvent · System 10 16.373 ns 0.75 -
SignalAndWait · AsyncCountdownEv · RefImpl 10 20.918 ns 0.96 96 B
SignalAndWait · AsyncCountdownEv · Pooled 10 21.765 ns 1.00 -
WaitAndSignal · AsyncCountdownEv · ProtoPromise 10 22.452 ns 1.03 -
WaitAndSignal · AsyncCountdownEv · Pooled 10 46.098 ns 2.12 -

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 7.495 ns 1.00 -
SignalAndWait · Barrier · System 1 1,049.935 ns 140.09 238 B
SignalAndWait · AsyncBarrier · RefImpl 1 1,674.585 ns 223.44 8470 B
SignalAndWait · AsyncBarrier · Pooled 10 201.242 ns 1.00 -
SignalAndWait · AsyncBarrier · RefImpl 10 1,852.928 ns 9.21 8693 B
SignalAndWait · Barrier · System 10 18,894.387 ns 93.89 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.635 ns 0.61 -
WriterLock · AsyncRWLock · Proto.Promises 6.804 ns 0.89 -
WriterLock · AsyncRWLock · Pooled 7.614 ns 1.00 -
WriterLock · AsyncRWLock · RefImpl 12.101 ns 1.59 -
WriterLock · AsyncRWLock · Nito.AsyncEx 57.229 ns 7.52 496 B
WriterLock · AsyncRWLock · VS.Threading 1,382.823 ns 181.62 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 5.888 ns 0.64 -
ReaderLock · AsyncRWLock · Pooled 0 None 9.213 ns 1.00 -
ReaderLock · AsyncRWLock · Proto.Promises 0 None 11.173 ns 1.21 -
ReaderLock · AsyncRWLock · RefImpl 0 None 14.129 ns 1.53 -
ReaderLock · AsyncRWLock · Nito.AsyncEx 0 None 41.797 ns 4.54 320 B
ReaderLock · AsyncRWLock · VS.Threading 0 None 168.990 ns 18.34 208 B
ReaderLock · AsyncRWLock · Pooled 0 NotCancelled 9.321 ns 1.00 -
ReaderLock · AsyncRWLock · Proto.Promises 0 NotCancelled 11.602 ns 1.24 -
ReaderLock · AsyncRWLock · Nito.AsyncEx 0 NotCancelled 41.122 ns 4.41 320 B
ReaderLock · AsyncRWLock · VS.Threading 0 NotCancelled 169.890 ns 18.23 208 B
ReaderLock · RWLockSlim · System 1 None 10.176 ns 0.22 -
ReaderLock · AsyncRWLock · Proto.Promises 1 None 15.947 ns 0.35 -
ReaderLock · AsyncRWLock · RefImpl 1 None 23.278 ns 0.51 -
ReaderLock · AsyncRWLock · Pooled 1 None 46.083 ns 1.00 -
ReaderLock · AsyncRWLock · Nito.AsyncEx 1 None 82.708 ns 1.79 640 B
ReaderLock · AsyncRWLock · VS.Threading 1 None 393.761 ns 8.54 416 B
ReaderLock · AsyncRWLock · Proto.Promises 1 NotCancelled 16.695 ns 0.37 -
ReaderLock · AsyncRWLock · Pooled 1 NotCancelled 45.499 ns 1.00 -
ReaderLock · AsyncRWLock · Nito.AsyncEx 1 NotCancelled 82.226 ns 1.81 640 B
ReaderLock · AsyncRWLock · VS.Threading 1 NotCancelled 392.648 ns 8.63 416 B
ReaderLock · RWLockSlim · System 10 None 51.441 ns 0.16 -
ReaderLock · AsyncRWLock · Proto.Promises 10 None 53.245 ns 0.17 -
ReaderLock · AsyncRWLock · RefImpl 10 None 113.986 ns 0.35 -
ReaderLock · AsyncRWLock · Pooled 10 None 321.143 ns 1.00 -
ReaderLock · AsyncRWLock · Nito.AsyncEx 10 None 465.151 ns 1.45 3520 B
ReaderLock · AsyncRWLock · VS.Threading 10 None 2,890.460 ns 9.00 2288 B
ReaderLock · AsyncRWLock · Proto.Promises 10 NotCancelled 54.657 ns 0.18 -
ReaderLock · AsyncRWLock · Pooled 10 NotCancelled 310.092 ns 1.00 -
ReaderLock · AsyncRWLock · Nito.AsyncEx 10 NotCancelled 469.412 ns 1.51 3520 B
ReaderLock · AsyncRWLock · VS.Threading 10 NotCancelled 2,874.892 ns 9.27 2288 B
ReaderLock · AsyncRWLock · Proto.Promises 100 None 458.458 ns 0.16 -
ReaderLock · RWLockSlim · System 100 None 482.223 ns 0.17 -
ReaderLock · AsyncRWLock · RefImpl 100 None 985.528 ns 0.35 -
ReaderLock · AsyncRWLock · Pooled 100 None 2,828.670 ns 1.00 -
ReaderLock · AsyncRWLock · Nito.AsyncEx 100 None 4,126.229 ns 1.46 32320 B
ReaderLock · AsyncRWLock · VS.Threading 100 None 74,059.595 ns 26.20 21008 B
ReaderLock · AsyncRWLock · Proto.Promises 100 NotCancelled 450.691 ns 0.17 -
ReaderLock · AsyncRWLock · Pooled 100 NotCancelled 2,713.733 ns 1.00 -
ReaderLock · AsyncRWLock · Nito.AsyncEx 100 NotCancelled 4,114.507 ns 1.52 32320 B
ReaderLock · AsyncRWLock · VS.Threading 100 NotCancelled 74,958.026 ns 27.62 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.973 ns 0.57 -
UpgradeableReaderLock · AsyncRWLock · Pooled 0 None 8.719 ns 1.00 -
UpgradeableReaderLock · AsyncRWLock · Proto.Promises 0 None 12.361 ns 1.42 -
UpgradeableReaderLock · AsyncRWLock · VS.Threading 0 None 1,389.283 ns 159.35 616 B
UpgradeableReaderLock · AsyncRWLock · Pooled 0 NotCancelled 8.703 ns 1.00 -
UpgradeableReaderLock · AsyncRWLock · Proto.Promises 0 NotCancelled 12.282 ns 1.41 -
UpgradeableReaderLock · AsyncRWLock · VS.Threading 0 NotCancelled 1,457.782 ns 167.50 616 B
UpgradeableReaderLock · RWLockSlim · System 1 None 4.973 ns 0.12 -
UpgradeableReaderLock · AsyncRWLock · Proto.Promises 1 None 10.892 ns 0.26 -
UpgradeableReaderLock · AsyncRWLock · Pooled 1 None 41.941 ns 1.00 -
UpgradeableReaderLock · AsyncRWLock · VS.Threading 1 None 1,452.258 ns 34.66 616 B
UpgradeableReaderLock · AsyncRWLock · Proto.Promises 1 NotCancelled 10.977 ns 0.26 -
UpgradeableReaderLock · AsyncRWLock · Pooled 1 NotCancelled 41.459 ns 1.00 -
UpgradeableReaderLock · AsyncRWLock · VS.Threading 1 NotCancelled 1,451.141 ns 35.01 616 B
UpgradeableReaderLock · RWLockSlim · System 2 None 4.969 ns 0.12 -
UpgradeableReaderLock · AsyncRWLock · Proto.Promises 2 None 10.851 ns 0.26 -
UpgradeableReaderLock · AsyncRWLock · Pooled 2 None 41.628 ns 1.00 -
UpgradeableReaderLock · AsyncRWLock · VS.Threading 2 None 1,363.634 ns 32.76 616 B
UpgradeableReaderLock · AsyncRWLock · Proto.Promises 2 NotCancelled 10.840 ns 0.27 -
UpgradeableReaderLock · AsyncRWLock · Pooled 2 NotCancelled 40.608 ns 1.00 -
UpgradeableReaderLock · AsyncRWLock · VS.Threading 2 NotCancelled 1,411.681 ns 34.78 616 B
UpgradeableReaderLock · RWLockSlim · System 5 None 19.236 ns 0.14 -
UpgradeableReaderLock · AsyncRWLock · Proto.Promises 5 None 22.858 ns 0.17 -
UpgradeableReaderLock · AsyncRWLock · Pooled 5 None 137.638 ns 1.00 -
UpgradeableReaderLock · AsyncRWLock · VS.Threading 5 None 2,130.834 ns 15.48 1240 B
UpgradeableReaderLock · AsyncRWLock · Proto.Promises 5 NotCancelled 23.752 ns 0.18 -
UpgradeableReaderLock · AsyncRWLock · Pooled 5 NotCancelled 130.160 ns 1.00 -
UpgradeableReaderLock · AsyncRWLock · VS.Threading 5 NotCancelled 2,157.943 ns 16.58 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.52 ns 0.62 -
UpgradedWriterLock · AsyncRWLock · Pooled 0 None 16.94 ns 1.00 -
UpgradedWriterLock · AsyncRWLock · Proto.Promises 0 None 21.61 ns 1.28 -
UpgradedWriterLock · AsyncRWLock · VS.Threading 0 None 1,552.73 ns 91.69 824 B
UpgradedWriterLock · AsyncRWLock · Pooled 0 NotCancelled 16.89 ns 1.00 -
UpgradedWriterLock · AsyncRWLock · Proto.Promises 0 NotCancelled 18.75 ns 1.11 -
UpgradedWriterLock · AsyncRWLock · VS.Threading 0 NotCancelled 1,651.64 ns 97.78 824 B
UpgradedWriterLock · RWLockSlim · System 1 None 16.72 ns 0.23 -
UpgradedWriterLock · AsyncRWLock · Proto.Promises 1 None 30.60 ns 0.41 -
UpgradedWriterLock · AsyncRWLock · Pooled 1 None 74.10 ns 1.00 -
UpgradedWriterLock · AsyncRWLock · VS.Threading 1 None 1,779.19 ns 24.01 1032 B
UpgradedWriterLock · AsyncRWLock · Proto.Promises 1 NotCancelled 42.98 ns 0.62 -
UpgradedWriterLock · AsyncRWLock · Pooled 1 NotCancelled 68.81 ns 1.00 -
UpgradedWriterLock · AsyncRWLock · VS.Threading 1 NotCancelled 1,945.10 ns 28.27 1032 B
UpgradedWriterLock · RWLockSlim · System 2 None 21.38 ns 0.16 -
UpgradedWriterLock · AsyncRWLock · Proto.Promises 2 None 34.28 ns 0.25 -
UpgradedWriterLock · AsyncRWLock · Pooled 2 None 135.45 ns 1.00 -
UpgradedWriterLock · AsyncRWLock · VS.Threading 2 None 2,147.03 ns 15.85 1240 B
UpgradedWriterLock · AsyncRWLock · Proto.Promises 2 NotCancelled 48.11 ns 0.37 -
UpgradedWriterLock · AsyncRWLock · Pooled 2 NotCancelled 129.10 ns 1.00 -
UpgradedWriterLock · AsyncRWLock · VS.Threading 2 NotCancelled 2,360.20 ns 18.28 1240 B
UpgradedWriterLock · RWLockSlim · System 5 None 34.02 ns 0.11 -
UpgradedWriterLock · AsyncRWLock · Proto.Promises 5 None 47.45 ns 0.15 -
UpgradedWriterLock · AsyncRWLock · Pooled 5 None 311.51 ns 1.00 -
UpgradedWriterLock · AsyncRWLock · VS.Threading 5 None 3,378.35 ns 10.85 1864 B
UpgradedWriterLock · AsyncRWLock · Proto.Promises 5 NotCancelled 58.82 ns 0.19 -
UpgradedWriterLock · AsyncRWLock · Pooled 5 NotCancelled 304.04 ns 1.00 -
UpgradedWriterLock · AsyncRWLock · VS.Threading 5 NotCancelled 3,474.43 ns 11.43 1864 B