Repository navigation
Tear down suspended coroutines through their chain's owner - #395
Merged
Merged
Conversation
run_task is entered without the scheduler lock when the caller has just handed queued work to a peer thread, and the snapshot then walked registered_descs_ while deregister_descriptor() erased from it under that lock. Take the lock for the snapshot when the caller released it.
Benchmark report
|
| Platform | Backend | Benchmark | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|---|
| linux | epoll | accept_churn/sequential | ops_per_sec | 14.85K ops/s | 15.40K ops/s | 🟢▲ +3.96% | 1.23% |
| linux | uring | accept_churn/burst/10 | ops_per_sec | 1.71K ops/s | 1.82K ops/s | 🟢▲ +6.23% | 1.11% |
| linux | uring | accept_churn/burst/100 | ops_per_sec | 174.1 ops/s | 187.0 ops/s | 🟢▲ +7.30% | 0.67% |
| linux | uring | accept_churn/burst_lockless/10 | ops_per_sec | 1.82K ops/s | 1.95K ops/s | 🟢▲ +6.64% | 1.16% |
| linux | uring | accept_churn/burst_lockless/100 | ops_per_sec | 186.0 ops/s | 200.6 ops/s | 🟢▲ +7.97% | 0.73% |
| linux | uring | accept_churn/concurrent/1 | ops_per_sec | 12.71K ops/s | 13.71K ops/s | 🟢▲ +8.17% | 1.27% |
| linux | uring | accept_churn/concurrent/16 | ops_per_sec | 12.60K ops/s | 13.63K ops/s | 🟢▲ +8.38% | 1.15% |
| linux | uring | accept_churn/concurrent/4 | ops_per_sec | 12.67K ops/s | 13.64K ops/s | 🟢▲ +7.23% | 1.06% |
| linux | uring | accept_churn/sequential | ops_per_sec | 12.75K ops/s | 13.74K ops/s | 🟢▲ +7.86% | 1.08% |
| linux | uring | accept_churn/sequential_lockless | ops_per_sec | 13.63K ops/s | 14.68K ops/s | 🟢▲ +7.49% | 1.16% |
| linux | uring | fan_out/concurrent_parents_lockless/1 | ops_per_sec | 3.65K ops/s | 3.50K ops/s | 🔴▼ -4.32% | 1.40% |
| linux | uring | fan_out/concurrent_parents_lockless/16 | ops_per_sec | 3.52K ops/s | 3.36K ops/s | 🔴▼ -4.76% | 1.05% |
| linux | uring | fan_out/concurrent_parents_lockless/4 | ops_per_sec | 3.55K ops/s | 3.40K ops/s | 🔴▼ -4.71% | 1.21% |
| linux | uring | fan_out/fork_join_lockless/16 | ops_per_sec | 3.65K ops/s | 3.47K ops/s | 🔴▼ -5.08% | 0.26% |
| linux | uring | fan_out/fork_join_lockless/4 | ops_per_sec | 14.51K ops/s | 13.87K ops/s | 🔴▼ -4.85% | 0.90% |
| linux | uring | fan_out/fork_join_lockless/64 | ops_per_sec | 865.4 ops/s | 824.8 ops/s | 🔴▼ -4.69% | 0.30% |
| linux | uring | fan_out/nested_lockless/16 | ops_per_sec | 854.6 ops/s | 819.2 ops/s | 🔴▼ -4.54% | 0.98% |
| linux | uring | fan_out/nested_lockless/4 | ops_per_sec | 3.61K ops/s | 3.45K ops/s | 🔴▼ -4.68% | 0.93% |
| linux | uring | http_server/multithread/16 | ops_per_sec | 81.44K ops/s | 83.21K ops/s | 🟢▲ +2.58% | 0.52% |
| linux | uring | local_socket_throughput/bidirectional_lockless/16384 | bytes_per_sec | 2.61 GB/s | 2.41 GB/s | 🔴▼ -7.57% | 1.48% |
| linux | uring | local_socket_throughput/bidirectional_lockless/65536 | bytes_per_sec | 3.18 GB/s | 3.00 GB/s | 🔴▼ -6.33% | 1.73% |
| linux | uring | local_socket_throughput/unidirectional_lockless/262144 | bytes_per_sec | 3.35 GB/s | 3.51 GB/s | 🟢▲ +5.95% | 1.88% |
| linux | uring | socket_throughput/bidirectional_lockless/1048576 | bytes_per_sec | 3.32 GB/s | 3.20 GB/s | 🔴▼ -3.44% | 0.84% |
| linux | uring | socket_throughput/bidirectional_lockless/262144 | bytes_per_sec | 3.24 GB/s | 3.13 GB/s | 🔴▼ -3.17% | 0.66% |
| windows | iocp | accept_churn/burst/10 | ops_per_sec | 1.53K ops/s | 1.56K ops/s | 🟢▲ +2.26% | 0.34% |
| windows | iocp | accept_churn/burst/100 | ops_per_sec | 149.6 ops/s | 157.2 ops/s | 🟢▲ +5.02% | 0.94% |
| windows | iocp | accept_churn/burst_lockless/10 | ops_per_sec | 1.53K ops/s | 1.57K ops/s | 🟢▲ +2.38% | 0.37% |
| windows | iocp | accept_churn/burst_lockless/100 | ops_per_sec | 151.9 ops/s | 160.0 ops/s | 🟢▲ +5.42% | 0.48% |
| windows | iocp | accept_churn/sequential_lockless | ops_per_sec | 12.28K ops/s | 12.55K ops/s | 🟢▲ +2.19% | 0.32% |
| macos | kqueue | accept_churn/burst/10 | ops_per_sec | 4.21K ops/s | 4.33K ops/s | 🟢▲ +2.75% | 0.88% |
| macos | kqueue | accept_churn/burst_lockless/10 | ops_per_sec | 4.27K ops/s | 4.37K ops/s | 🟢▲ +2.50% | 0.57% |
| macos | kqueue | accept_churn/concurrent/16 | ops_per_sec | 35.19K ops/s | 36.38K ops/s | 🟢▲ +3.44% | 0.95% |
linux — full results (226 benchmarks, 5 iterations, 1.5s each)
accept_churn
| Benchmark | Backend | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|
| burst/10 | epoll | ops_per_sec | 1.88K ops/s | 1.91K ops/s | 🟢▲ +1.92% | 0.90% |
| burst/10 | uring | ops_per_sec | 1.71K ops/s | 1.82K ops/s | 🟢▲ +6.23% | 1.11% |
| burst/100 | epoll | ops_per_sec | 189.9 ops/s | 193.6 ops/s | 🟢▲ +2.13% | 0.82% |
| burst/100 | uring | ops_per_sec | 174.1 ops/s | 187.0 ops/s | 🟢▲ +7.30% | 0.67% |
| burst_lockless/10 | epoll | ops_per_sec | 1.90K ops/s | 1.94K ops/s | 🟢▲ +2.16% | 1.27% |
| burst_lockless/10 | uring | ops_per_sec | 1.82K ops/s | 1.95K ops/s | 🟢▲ +6.64% | 1.16% |
| burst_lockless/100 | epoll | ops_per_sec | 192.0 ops/s | 195.9 ops/s | 🟢▲ +2.45% | 1.21% |
| burst_lockless/100 | uring | ops_per_sec | 186.0 ops/s | 200.6 ops/s | 🟢▲ +7.97% | 0.73% |
| concurrent/1 | epoll | ops_per_sec | 14.85K ops/s | 15.28K ops/s | 🟢▲ +2.99% | 1.16% |
| concurrent/1 | uring | ops_per_sec | 12.71K ops/s | 13.71K ops/s | 🟢▲ +8.17% | 1.27% |
| concurrent/16 | epoll | ops_per_sec | 14.97K ops/s | 15.31K ops/s | 🟢▲ +2.19% | 0.97% |
| concurrent/16 | uring | ops_per_sec | 12.60K ops/s | 13.63K ops/s | 🟢▲ +8.38% | 1.15% |
| concurrent/4 | epoll | ops_per_sec | 14.92K ops/s | 15.31K ops/s | 🟢▲ +2.29% | 1.25% |
| concurrent/4 | uring | ops_per_sec | 12.67K ops/s | 13.64K ops/s | 🟢▲ +7.23% | 1.06% |
| sequential | epoll | ops_per_sec | 14.85K ops/s | 15.40K ops/s | 🟢▲ +3.96% | 1.23% |
| sequential | uring | ops_per_sec | 12.75K ops/s | 13.74K ops/s | 🟢▲ +7.86% | 1.08% |
| sequential_lockless | epoll | ops_per_sec | 14.94K ops/s | 15.54K ops/s | 🟢▲ +3.29% | 1.13% |
| sequential_lockless | uring | ops_per_sec | 13.63K ops/s | 14.68K ops/s | 🟢▲ +7.49% | 1.16% |
fan_out
| Benchmark | Backend | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|
| concurrent_parents/1 | epoll | ops_per_sec | 3.70K ops/s | 3.69K ops/s | 🔴▼ -0.38% | 1.08% |
| concurrent_parents/1 | uring | ops_per_sec | 3.42K ops/s | 3.45K ops/s | 🟢▲ +0.28% | 1.05% |
| concurrent_parents/16 | epoll | ops_per_sec | 3.59K ops/s | 3.58K ops/s | ⚪ 0.00% | 0.59% |
| concurrent_parents/16 | uring | ops_per_sec | 3.30K ops/s | 3.34K ops/s | 🟢▲ +0.30% | 1.30% |
| concurrent_parents/4 | epoll | ops_per_sec | 3.60K ops/s | 3.61K ops/s | 🟢▲ +0.09% | 0.92% |
| concurrent_parents/4 | uring | ops_per_sec | 3.33K ops/s | 3.37K ops/s | 🟢▲ +0.15% | 1.27% |
| concurrent_parents_lockless/1 | epoll | ops_per_sec | 3.72K ops/s | 3.71K ops/s | 🔴▼ -0.30% | 0.26% |
| concurrent_parents_lockless/1 | uring | ops_per_sec | 3.65K ops/s | 3.50K ops/s | 🔴▼ -4.32% | 1.40% |
| concurrent_parents_lockless/16 | epoll | ops_per_sec | 3.61K ops/s | 3.61K ops/s | 🟢▲ +0.09% | 0.22% |
| concurrent_parents_lockless/16 | uring | ops_per_sec | 3.52K ops/s | 3.36K ops/s | 🔴▼ -4.76% | 1.05% |
| concurrent_parents_lockless/4 | epoll | ops_per_sec | 3.63K ops/s | 3.63K ops/s | 🔴▼ -0.20% | 0.20% |
| concurrent_parents_lockless/4 | uring | ops_per_sec | 3.55K ops/s | 3.40K ops/s | 🔴▼ -4.71% | 1.21% |
| fork_join/1 | epoll | ops_per_sec | 54.94K ops/s | 54.68K ops/s | 🔴▼ -0.18% | 1.23% |
| fork_join/1 | uring | ops_per_sec | 53.08K ops/s | 53.56K ops/s | 🟢▲ +0.46% | 1.32% |
| fork_join/16 | epoll | ops_per_sec | 3.70K ops/s | 3.70K ops/s | 🔴▼ -0.04% | 1.27% |
| fork_join/16 | uring | ops_per_sec | 3.43K ops/s | 3.46K ops/s | 🟢▲ +0.14% | 1.42% |
| fork_join/4 | epoll | ops_per_sec | 14.67K ops/s | 14.65K ops/s | 🔴▼ -0.18% | 1.07% |
| fork_join/4 | uring | ops_per_sec | 13.69K ops/s | 13.80K ops/s | 🟢▲ +0.25% | 1.29% |
| fork_join/64 | epoll | ops_per_sec | 902.3 ops/s | 905.4 ops/s | 🔴▼ -0.05% | 1.30% |
| fork_join/64 | uring | ops_per_sec | 811.7 ops/s | 818.3 ops/s | 🟢▲ +0.57% | 0.94% |
| fork_join_lockless/1 | epoll | ops_per_sec | 55.62K ops/s | 55.75K ops/s | 🟢▲ +0.08% | 1.25% |
| fork_join_lockless/1 | uring | ops_per_sec | 55.67K ops/s | 54.00K ops/s | 🔴▼ -3.45% | 1.25% |
| fork_join_lockless/16 | epoll | ops_per_sec | 3.74K ops/s | 3.75K ops/s | 🔴▼ -0.25% | 1.29% |
| fork_join_lockless/16 | uring | ops_per_sec | 3.65K ops/s | 3.47K ops/s | 🔴▼ -5.08% | 0.26% |
| fork_join_lockless/4 | epoll | ops_per_sec | 14.88K ops/s | 14.89K ops/s | 🔴▼ -0.40% | 1.18% |
| fork_join_lockless/4 | uring | ops_per_sec | 14.51K ops/s | 13.87K ops/s | 🔴▼ -4.85% | 0.90% |
| fork_join_lockless/64 | epoll | ops_per_sec | 913.0 ops/s | 917.8 ops/s | 🔴▼ -0.14% | 1.10% |
| fork_join_lockless/64 | uring | ops_per_sec | 865.4 ops/s | 824.8 ops/s | 🔴▼ -4.69% | 0.30% |
| nested/16 | epoll | ops_per_sec | 899.3 ops/s | 898.3 ops/s | 🔴▼ -0.11% | 1.21% |
| nested/16 | uring | ops_per_sec | 802.3 ops/s | 803.1 ops/s | 🔴▼ -0.02% | 0.26% |
| nested/4 | epoll | ops_per_sec | 3.69K ops/s | 3.70K ops/s | 🔴▼ -0.24% | 1.39% |
| nested/4 | uring | ops_per_sec | 3.39K ops/s | 3.39K ops/s | 🟢▲ +0.11% | 0.14% |
| nested_lockless/16 | epoll | ops_per_sec | 908.1 ops/s | 903.9 ops/s | 🔴▼ -0.28% | 0.97% |
| nested_lockless/16 | uring | ops_per_sec | 854.6 ops/s | 819.2 ops/s | 🔴▼ -4.54% | 0.98% |
| nested_lockless/4 | epoll | ops_per_sec | 3.74K ops/s | 3.73K ops/s | 🔴▼ -0.22% | 1.35% |
| nested_lockless/4 | uring | ops_per_sec | 3.61K ops/s | 3.45K ops/s | 🔴▼ -4.68% | 0.93% |
http_server
| Benchmark | Backend | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|
| concurrent/1 | epoll | ops_per_sec | 54.88K ops/s | 54.86K ops/s | 🔴▼ -0.23% | 0.77% |
| concurrent/1 | uring | ops_per_sec | 53.34K ops/s | 53.85K ops/s | 🟢▲ +0.45% | 1.21% |
| concurrent/16 | epoll | ops_per_sec | 58.07K ops/s | 58.05K ops/s | 🔴▼ -0.45% | 1.37% |
| concurrent/16 | uring | ops_per_sec | 52.78K ops/s | 52.91K ops/s | 🟢▲ +0.22% | 0.26% |
| concurrent/32 | epoll | ops_per_sec | 57.66K ops/s | 57.71K ops/s | 🔴▼ -0.67% | 1.48% |
| concurrent/32 | uring | ops_per_sec | 52.46K ops/s | 52.49K ops/s | 🔴▼ -0.08% | 0.21% |
| concurrent/4 | epoll | ops_per_sec | 57.35K ops/s | 57.16K ops/s | 🔴▼ -0.62% | 1.16% |
| concurrent/4 | uring | ops_per_sec | 52.82K ops/s | 53.33K ops/s | 🟢▲ +0.73% | 0.90% |
| multithread/1 | epoll | ops_per_sec | 57.54K ops/s | 57.64K ops/s | 🔴▼ -0.25% | 1.29% |
| multithread/1 | uring | ops_per_sec | 52.46K ops/s | 52.53K ops/s | 🟢▲ +0.22% | 0.27% |
| multithread/16 | epoll | ops_per_sec | 161.2K ops/s | 161.3K ops/s | 🟢▲ +0.37% | 0.58% |
| multithread/16 | uring | ops_per_sec | 81.44K ops/s | 83.21K ops/s | 🟢▲ +2.58% | 0.52% |
| multithread/2 | epoll | ops_per_sec | 86.59K ops/s | 86.48K ops/s | 🔴▼ -0.31% | 0.39% |
| multithread/2 | uring | ops_per_sec | 90.29K ops/s | 91.00K ops/s | 🟢▲ +0.47% | 1.28% |
| multithread/4 | epoll | ops_per_sec | 157.9K ops/s | 158.0K ops/s | 🟢▲ +0.01% | 1.04% |
| multithread/4 | uring | ops_per_sec | 79.60K ops/s | 80.18K ops/s | 🟢▲ +0.87% | 0.84% |
| multithread/8 | epoll | ops_per_sec | 160.6K ops/s | 160.6K ops/s | ⚪ 0.00% | 0.42% |
| multithread/8 | uring | ops_per_sec | 77.24K ops/s | 72.05K ops/s | 🟢▲ +1.13% | 19.47% |
| single_conn | epoll | ops_per_sec | 54.92K ops/s | 54.71K ops/s | 🔴▼ -0.18% | 0.26% |
| single_conn | uring | ops_per_sec | 53.32K ops/s | 53.84K ops/s | 🟢▲ +0.74% | 1.11% |
| single_conn_lockless | epoll | ops_per_sec | 55.61K ops/s | 55.46K ops/s | 🔴▼ -0.24% | 0.20% |
| single_conn_lockless | uring | ops_per_sec | 55.92K ops/s | 54.41K ops/s | 🔴▼ -3.26% | 1.28% |
local_socket_latency
| Benchmark | Backend | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|
| concurrent/1 | epoll | latency_mean_ns | 7.29 µs | 7.26 µs | 🔴▼ -0.24% | 4.89% |
| concurrent/1 | uring | latency_mean_ns | 6.59 µs | 6.76 µs | 🔴▼ -0.59% | 4.44% |
| concurrent/16 | epoll | latency_mean_ns | 109.76 µs | 110.34 µs | 🔴▼ -0.48% | 0.90% |
| concurrent/16 | uring | latency_mean_ns | 108.44 µs | 108.90 µs | 🔴▼ -0.43% | 0.36% |
| concurrent/4 | epoll | latency_mean_ns | 27.49 µs | 27.97 µs | 🔴▼ -2.09% | 2.19% |
| concurrent/4 | uring | latency_mean_ns | 27.08 µs | 27.18 µs | 🔴▼ -0.64% | 1.22% |
| concurrent_lockless/1 | epoll | latency_mean_ns | 6.98 µs | 7.15 µs | 🔴▼ -0.09% | 4.14% |
| concurrent_lockless/1 | uring | latency_mean_ns | 6.83 µs | 6.70 µs | 🔴▼ -0.34% | 5.44% |
| concurrent_lockless/16 | epoll | latency_mean_ns | 108.93 µs | 109.01 µs | 🟢▲ +0.07% | 0.53% |
| concurrent_lockless/16 | uring | latency_mean_ns | 107.99 µs | 107.81 µs | 🔴▼ -0.15% | 0.81% |
| concurrent_lockless/4 | epoll | latency_mean_ns | 27.58 µs | 27.43 µs | 🟢▲ +0.53% | 1.07% |
| concurrent_lockless/4 | uring | latency_mean_ns | 27.11 µs | 27.02 µs | 🔴▼ -0.56% | 1.37% |
| pingpong/1 | epoll | latency_mean_ns | 7.33 µs | 7.21 µs | 🟢▲ +0.20% | 5.08% |
| pingpong/1 | uring | latency_mean_ns | 6.83 µs | 6.52 µs | 🟢▲ +4.48% | 4.07% |
| pingpong/1024 | epoll | latency_mean_ns | 8.04 µs | 7.89 µs | 🟢▲ +0.25% | 3.86% |
| pingpong/1024 | uring | latency_mean_ns | 7.23 µs | 7.23 µs | 🔴▼ -0.64% | 5.14% |
| pingpong/64 | epoll | latency_mean_ns | 7.53 µs | 7.26 µs | 🟢▲ +1.11% | 5.18% |
| pingpong/64 | uring | latency_mean_ns | 6.65 µs | 6.57 µs | 🔴▼ -0.08% | 2.06% |
| pingpong_lockless/1 | epoll | latency_mean_ns | 7.11 µs | 7.10 µs | 🟢▲ +0.37% | 4.40% |
| pingpong_lockless/1 | uring | latency_mean_ns | 6.80 µs | 6.53 µs | 🟢▲ +0.10% | 5.30% |
| pingpong_lockless/1024 | epoll | latency_mean_ns | 7.56 µs | 7.77 µs | 🔴▼ -2.03% | 3.88% |
| pingpong_lockless/1024 | uring | latency_mean_ns | 7.33 µs | 6.97 µs | 🟢▲ +8.04% | 4.39% |
| pingpong_lockless/64 | epoll | latency_mean_ns | 6.99 µs | 7.03 µs | 🟢▲ +0.26% | 1.11% |
| pingpong_lockless/64 | uring | latency_mean_ns | 6.96 µs | 6.72 µs | 🟢▲ +0.30% | 5.15% |
local_socket_throughput
| Benchmark | Backend | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|
| bidirectional/1024 | epoll | bytes_per_sec | 302.8 MB/s | 304.2 MB/s | 🟢▲ +0.77% | 1.05% |
| bidirectional/1024 | uring | bytes_per_sec | 301.9 MB/s | 301.9 MB/s | 🔴▼ -0.06% | 0.87% |
| bidirectional/1048576 | epoll | bytes_per_sec | 3.21 GB/s | 3.17 GB/s | 🟢▲ +0.48% | 2.79% |
| bidirectional/1048576 | uring | bytes_per_sec | 3.33 GB/s | 3.28 GB/s | 🔴▼ -0.17% | 2.25% |
| bidirectional/16384 | epoll | bytes_per_sec | 3.08 GB/s | 3.01 GB/s | 🟢▲ +0.53% | 4.73% |
| bidirectional/16384 | uring | bytes_per_sec | 2.42 GB/s | 2.41 GB/s | 🔴▼ -0.33% | 0.65% |
| bidirectional/262144 | epoll | bytes_per_sec | 3.22 GB/s | 3.20 GB/s | 🟢▲ +0.57% | 2.56% |
| bidirectional/262144 | uring | bytes_per_sec | 3.29 GB/s | 3.32 GB/s | 🟢▲ +0.82% | 2.36% |
| bidirectional/4096 | epoll | bytes_per_sec | 999.9 MB/s | 1.00 GB/s | 🟢▲ +0.02% | 0.58% |
| bidirectional/4096 | uring | bytes_per_sec | 989.1 MB/s | 988.4 MB/s | 🔴▼ -0.66% | 1.09% |
| bidirectional/65536 | epoll | bytes_per_sec | 2.95 GB/s | 2.95 GB/s | 🟢▲ +0.68% | 1.28% |
| bidirectional/65536 | uring | bytes_per_sec | 3.01 GB/s | 3.00 GB/s | 🔴▼ -0.40% | 1.61% |
| bidirectional_lockless/1024 | epoll | bytes_per_sec | 312.1 MB/s | 305.2 MB/s | 🔴▼ -2.10% | 1.89% |
| bidirectional_lockless/1024 | uring | bytes_per_sec | 303.5 MB/s | 301.3 MB/s | 🔴▼ -0.64% | 0.48% |
| bidirectional_lockless/1048576 | epoll | bytes_per_sec | 3.18 GB/s | 3.18 GB/s | 🟢▲ +0.60% | 2.98% |
| bidirectional_lockless/1048576 | uring | bytes_per_sec | 3.36 GB/s | 3.27 GB/s | 🔴▼ -1.44% | 2.59% |
| bidirectional_lockless/16384 | epoll | bytes_per_sec | 3.07 GB/s | 3.05 GB/s | 🟢▲ +0.72% | 3.88% |
| bidirectional_lockless/16384 | uring | bytes_per_sec | 2.61 GB/s | 2.41 GB/s | 🔴▼ -7.57% | 1.48% |
| bidirectional_lockless/262144 | epoll | bytes_per_sec | 3.19 GB/s | 3.20 GB/s | 🟢▲ +0.12% | 2.66% |
| bidirectional_lockless/262144 | uring | bytes_per_sec | 3.33 GB/s | 3.30 GB/s | 🔴▼ -1.52% | 2.16% |
| bidirectional_lockless/4096 | epoll | bytes_per_sec | 1.02 GB/s | 1.01 GB/s | 🟢▲ +0.07% | 1.20% |
| bidirectional_lockless/4096 | uring | bytes_per_sec | 992.5 MB/s | 990.3 MB/s | 🔴▼ -0.31% | 1.10% |
| bidirectional_lockless/65536 | epoll | bytes_per_sec | 2.96 GB/s | 2.95 GB/s | 🔴▼ -0.35% | 1.48% |
| bidirectional_lockless/65536 | uring | bytes_per_sec | 3.18 GB/s | 3.00 GB/s | 🔴▼ -6.33% | 1.73% |
| unidirectional/1024 | epoll | bytes_per_sec | 296.0 MB/s | 297.4 MB/s | 🟢▲ +0.12% | 0.88% |
| unidirectional/1024 | uring | bytes_per_sec | 303.1 MB/s | 301.7 MB/s | 🔴▼ -0.22% | 0.82% |
| unidirectional/1048576 | epoll | bytes_per_sec | 3.34 GB/s | 3.30 GB/s | 🔴▼ -0.14% | 2.90% |
| unidirectional/1048576 | uring | bytes_per_sec | 3.45 GB/s | 3.43 GB/s | 🔴▼ -0.39% | 1.98% |
| unidirectional/16384 | epoll | bytes_per_sec | 3.09 GB/s | 3.04 GB/s | 🔴▼ -0.70% | 2.87% |
| unidirectional/16384 | uring | bytes_per_sec | 2.58 GB/s | 2.65 GB/s | 🟢▲ +3.69% | 1.58% |
| unidirectional/262144 | epoll | bytes_per_sec | 3.35 GB/s | 3.30 GB/s | 🔴▼ -0.61% | 3.16% |
| unidirectional/262144 | uring | bytes_per_sec | 3.39 GB/s | 3.47 GB/s | 🟢▲ +3.05% | 2.21% |
| unidirectional/4096 | epoll | bytes_per_sec | 982.4 MB/s | 978.9 MB/s | 🔴▼ -0.01% | 1.01% |
| unidirectional/4096 | uring | bytes_per_sec | 995.6 MB/s | 984.5 MB/s | 🔴▼ -0.64% | 0.87% |
| unidirectional/65536 | epoll | bytes_per_sec | 3.22 GB/s | 3.27 GB/s | 🟢▲ +2.32% | 2.34% |
| unidirectional/65536 | uring | bytes_per_sec | 3.31 GB/s | 3.24 GB/s | 🔴▼ -2.51% | 2.65% |
| unidirectional_lockless/1024 | epoll | bytes_per_sec | 302.3 MB/s | 300.0 MB/s | 🔴▼ -0.93% | 1.57% |
| unidirectional_lockless/1024 | uring | bytes_per_sec | 303.5 MB/s | 303.4 MB/s | 🔴▼ -0.21% | 1.05% |
| unidirectional_lockless/1048576 | epoll | bytes_per_sec | 3.35 GB/s | 3.32 GB/s | 🔴▼ -1.10% | 3.14% |
| unidirectional_lockless/1048576 | uring | bytes_per_sec | 3.42 GB/s | 3.45 GB/s | 🟢▲ +1.55% | 2.35% |
| unidirectional_lockless/16384 | epoll | bytes_per_sec | 3.14 GB/s | 3.12 GB/s | 🔴▼ -0.55% | 1.67% |
| unidirectional_lockless/16384 | uring | bytes_per_sec | 2.65 GB/s | 2.66 GB/s | 🔴▼ -0.09% | 2.37% |
| unidirectional_lockless/262144 | epoll | bytes_per_sec | 3.35 GB/s | 3.31 GB/s | 🔴▼ -0.08% | 3.16% |
| unidirectional_lockless/262144 | uring | bytes_per_sec | 3.35 GB/s | 3.51 GB/s | 🟢▲ +5.95% | 1.88% |
| unidirectional_lockless/4096 | epoll | bytes_per_sec | 992.8 MB/s | 995.1 MB/s | 🟢▲ +0.24% | 1.63% |
| unidirectional_lockless/4096 | uring | bytes_per_sec | 990.1 MB/s | 998.1 MB/s | 🟢▲ +0.15% | 1.04% |
| unidirectional_lockless/65536 | epoll | bytes_per_sec | 3.25 GB/s | 3.30 GB/s | 🔴▼ -0.20% | 2.15% |
| unidirectional_lockless/65536 | uring | bytes_per_sec | 3.27 GB/s | 3.25 GB/s | 🔴▼ -0.18% | 2.63% |
socket_latency
| Benchmark | Backend | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|
| concurrent/1 | epoll | latency_mean_ns | 14.73 µs | 14.72 µs | 🟢▲ +0.26% | 1.36% |
| concurrent/1 | uring | latency_mean_ns | 14.53 µs | 14.54 µs | 🔴▼ -0.13% | 0.28% |
| concurrent/16 | epoll | latency_mean_ns | 232.66 µs | 233.14 µs | 🔴▼ -0.08% | 0.44% |
| concurrent/16 | uring | latency_mean_ns | 235.36 µs | 235.32 µs | 🔴▼ -0.03% | 0.12% |
| concurrent/4 | epoll | latency_mean_ns | 57.90 µs | 58.01 µs | 🟢▲ +0.04% | 1.22% |
| concurrent/4 | uring | latency_mean_ns | 58.37 µs | 58.45 µs | 🔴▼ -0.31% | 0.17% |
| concurrent_lockless/1 | epoll | latency_mean_ns | 14.69 µs | 14.68 µs | 🟢▲ +0.19% | 0.16% |
| concurrent_lockless/1 | uring | latency_mean_ns | 14.51 µs | 14.48 µs | 🔴▼ -0.10% | 0.97% |
| concurrent_lockless/16 | epoll | latency_mean_ns | 231.45 µs | 231.85 µs | 🔴▼ -0.21% | 0.12% |
| concurrent_lockless/16 | uring | latency_mean_ns | 235.25 µs | 234.07 µs | 🟢▲ +0.03% | 1.27% |
| concurrent_lockless/4 | epoll | latency_mean_ns | 57.80 µs | 57.81 µs | ⚪ 0.00% | 0.10% |
| concurrent_lockless/4 | uring | latency_mean_ns | 58.26 µs | 58.12 µs | 🔴▼ -0.31% | 1.29% |
| pingpong/1 | epoll | latency_mean_ns | 14.69 µs | 14.73 µs | 🟢▲ +0.30% | 1.30% |
| pingpong/1 | uring | latency_mean_ns | 14.47 µs | 14.43 µs | 🔴▼ -0.10% | 1.20% |
| pingpong/1024 | epoll | latency_mean_ns | 15.02 µs | 15.00 µs | 🟢▲ +0.27% | 1.37% |
| pingpong/1024 | uring | latency_mean_ns | 14.81 µs | 14.81 µs | 🔴▼ -0.22% | 0.65% |
| pingpong/64 | epoll | latency_mean_ns | 14.73 µs | 14.72 µs | 🟢▲ +0.30% | 1.16% |
| pingpong/64 | uring | latency_mean_ns | 14.55 µs | 14.50 µs | 🔴▼ -0.07% | 1.27% |
| pingpong_lockless/1 | epoll | latency_mean_ns | 14.57 µs | 14.55 µs | 🟢▲ +0.10% | 1.35% |
| pingpong_lockless/1 | uring | latency_mean_ns | 14.44 µs | 14.47 µs | 🔴▼ -0.19% | 0.30% |
| pingpong_lockless/1024 | epoll | latency_mean_ns | 14.90 µs | 14.87 µs | 🟢▲ +0.33% | 1.50% |
| pingpong_lockless/1024 | uring | latency_mean_ns | 14.76 µs | 14.82 µs | 🔴▼ -0.38% | 0.22% |
| pingpong_lockless/64 | epoll | latency_mean_ns | 14.63 µs | 14.62 µs | 🟢▲ +0.20% | 1.38% |
| pingpong_lockless/64 | uring | latency_mean_ns | 14.51 µs | 14.56 µs | 🔴▼ -0.39% | 0.25% |
socket_throughput
| Benchmark | Backend | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|
| bidirectional/1024 | epoll | bytes_per_sec | 133.6 MB/s | 134.3 MB/s | 🟢▲ +0.51% | 1.29% |
| bidirectional/1024 | uring | bytes_per_sec | 140.6 MB/s | 140.3 MB/s | 🔴▼ -0.38% | 0.35% |
| bidirectional/1048576 | epoll | bytes_per_sec | 3.27 GB/s | 3.27 GB/s | 🔴▼ -0.30% | 2.03% |
| bidirectional/1048576 | uring | bytes_per_sec | 3.22 GB/s | 3.21 GB/s | 🔴▼ -0.44% | 0.90% |
| bidirectional/16384 | epoll | bytes_per_sec | 1.63 GB/s | 1.64 GB/s | 🟢▲ +0.84% | 0.85% |
| bidirectional/16384 | uring | bytes_per_sec | 1.52 GB/s | 1.52 GB/s | 🟢▲ +1.08% | 1.82% |
| bidirectional/262144 | epoll | bytes_per_sec | 3.19 GB/s | 3.22 GB/s | 🟢▲ +1.41% | 1.06% |
| bidirectional/262144 | uring | bytes_per_sec | 3.18 GB/s | 3.15 GB/s | 🔴▼ -1.26% | 0.92% |
| bidirectional/4096 | epoll | bytes_per_sec | 504.3 MB/s | 506.3 MB/s | 🟢▲ +0.23% | 1.21% |
| bidirectional/4096 | uring | bytes_per_sec | 490.8 MB/s | 490.6 MB/s | 🔴▼ -0.22% | 0.68% |
| bidirectional/65536 | epoll | bytes_per_sec | 2.55 GB/s | 2.61 GB/s | 🟢▲ +0.21% | 4.18% |
| bidirectional/65536 | uring | bytes_per_sec | 2.82 GB/s | 2.78 GB/s | 🔴▼ -1.31% | 3.04% |
| bidirectional_lockless/1024 | epoll | bytes_per_sec | 134.0 MB/s | 133.9 MB/s | 🔴▼ -0.07% | 0.35% |
| bidirectional_lockless/1024 | uring | bytes_per_sec | 140.8 MB/s | 140.8 MB/s | 🔴▼ -0.15% | 0.39% |
| bidirectional_lockless/1048576 | epoll | bytes_per_sec | 3.26 GB/s | 3.32 GB/s | 🟢▲ +1.90% | 2.65% |
| bidirectional_lockless/1048576 | uring | bytes_per_sec | 3.32 GB/s | 3.20 GB/s | 🔴▼ -3.44% | 0.84% |
| bidirectional_lockless/16384 | epoll | bytes_per_sec | 1.63 GB/s | 1.63 GB/s | 🟢▲ +0.03% | 1.03% |
| bidirectional_lockless/16384 | uring | bytes_per_sec | 1.54 GB/s | 1.53 GB/s | 🔴▼ -0.48% | 0.71% |
| bidirectional_lockless/262144 | epoll | bytes_per_sec | 3.19 GB/s | 3.23 GB/s | 🟢▲ +1.11% | 1.02% |
| bidirectional_lockless/262144 | uring | bytes_per_sec | 3.24 GB/s | 3.13 GB/s | 🔴▼ -3.17% | 0.66% |
| bidirectional_lockless/4096 | epoll | bytes_per_sec | 505.5 MB/s | 503.9 MB/s | 🔴▼ -0.56% | 0.68% |
| bidirectional_lockless/4096 | uring | bytes_per_sec | 494.3 MB/s | 493.9 MB/s | 🔴▼ -0.06% | 0.39% |
| bidirectional_lockless/65536 | epoll | bytes_per_sec | 2.53 GB/s | 2.53 GB/s | 🟢▲ +0.22% | 2.77% |
| bidirectional_lockless/65536 | uring | bytes_per_sec | 2.75 GB/s | 2.75 GB/s | 🔴▼ -0.73% | 2.33% |
| multithread/2 | epoll | bytes_per_sec | 3.41 GB/s | 3.41 GB/s | 🔴▼ -0.08% | 0.64% |
| multithread/2 | uring | bytes_per_sec | 3.66 GB/s | 3.67 GB/s | 🟢▲ +0.03% | 0.71% |
| multithread/4 | epoll | bytes_per_sec | 4.86 GB/s | 4.87 GB/s | 🟢▲ +0.37% | 0.77% |
| multithread/4 | uring | bytes_per_sec | 5.08 GB/s | 5.06 GB/s | 🔴▼ -0.30% | 0.26% |
| multithread/8 | epoll | bytes_per_sec | 4.96 GB/s | 4.95 GB/s | 🔴▼ -0.10% | 0.33% |
| multithread/8 | uring | bytes_per_sec | 5.13 GB/s | 5.12 GB/s | 🟢▲ +0.07% | 0.23% |
| unidirectional/1024 | epoll | bytes_per_sec | 125.2 MB/s | 126.2 MB/s | 🟢▲ +0.38% | 1.20% |
| unidirectional/1024 | uring | bytes_per_sec | 139.1 MB/s | 139.3 MB/s | 🟢▲ +0.05% | 0.93% |
| unidirectional/1048576 | epoll | bytes_per_sec | 3.34 GB/s | 3.34 GB/s | 🟢▲ +0.10% | 0.92% |
| unidirectional/1048576 | uring | bytes_per_sec | 3.40 GB/s | 3.41 GB/s | 🟢▲ +0.55% | 0.90% |
| unidirectional/16384 | epoll | bytes_per_sec | 1.53 GB/s | 1.54 GB/s | 🟢▲ +1.38% | 1.29% |
| unidirectional/16384 | uring | bytes_per_sec | 1.57 GB/s | 1.57 GB/s | 🔴▼ -0.22% | 3.14% |
| unidirectional/262144 | epoll | bytes_per_sec | 3.27 GB/s | 3.28 GB/s | 🟢▲ +0.41% | 1.33% |
| unidirectional/262144 | uring | bytes_per_sec | 3.19 GB/s | 3.18 GB/s | 🔴▼ -0.02% | 1.42% |
| unidirectional/4096 | epoll | bytes_per_sec | 470.0 MB/s | 472.5 MB/s | 🟢▲ +0.69% | 0.56% |
| unidirectional/4096 | uring | bytes_per_sec | 490.8 MB/s | 489.3 MB/s | 🔴▼ -0.08% | 0.77% |
| unidirectional/65536 | epoll | bytes_per_sec | 2.65 GB/s | 2.73 GB/s | 🟢▲ +1.09% | 5.19% |
| unidirectional/65536 | uring | bytes_per_sec | 2.72 GB/s | 2.70 GB/s | 🔴▼ -0.90% | 0.53% |
| unidirectional_lockless/1024 | epoll | bytes_per_sec | 125.8 MB/s | 125.8 MB/s | 🔴▼ -0.08% | 0.18% |
| unidirectional_lockless/1024 | uring | bytes_per_sec | 139.4 MB/s | 139.0 MB/s | 🔴▼ -0.25% | 0.21% |
| unidirectional_lockless/1048576 | epoll | bytes_per_sec | 3.32 GB/s | 3.37 GB/s | 🟢▲ +1.91% | 1.17% |
| unidirectional_lockless/1048576 | uring | bytes_per_sec | 3.30 GB/s | 3.36 GB/s | 🟢▲ +1.73% | 1.50% |
| unidirectional_lockless/16384 | epoll | bytes_per_sec | 1.56 GB/s | 1.55 GB/s | 🔴▼ -0.12% | 0.77% |
| unidirectional_lockless/16384 | uring | bytes_per_sec | 1.58 GB/s | 1.57 GB/s | 🟢▲ +0.13% | 2.85% |
| unidirectional_lockless/262144 | epoll | bytes_per_sec | 3.32 GB/s | 3.37 GB/s | 🟢▲ +1.79% | 1.31% |
| unidirectional_lockless/262144 | uring | bytes_per_sec | 3.22 GB/s | 3.23 GB/s | 🟢▲ +0.21% | 1.33% |
| unidirectional_lockless/4096 | epoll | bytes_per_sec | 472.4 MB/s | 471.0 MB/s | 🔴▼ -0.09% | 0.45% |
| unidirectional_lockless/4096 | uring | bytes_per_sec | 491.3 MB/s | 488.3 MB/s | 🔴▼ -0.54% | 0.35% |
| unidirectional_lockless/65536 | epoll | bytes_per_sec | 2.67 GB/s | 2.77 GB/s | 🟢▲ +0.41% | 4.74% |
| unidirectional_lockless/65536 | uring | bytes_per_sec | 2.70 GB/s | 2.73 GB/s | 🔴▼ -0.14% | 2.95% |
windows — full results (77 benchmarks, 5 iterations, 1.5s each)
accept_churn
| Benchmark | Backend | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|
| burst/10 | iocp | ops_per_sec | 1.53K ops/s | 1.56K ops/s | 🟢▲ +2.26% | 0.34% |
| burst/100 | iocp | ops_per_sec | 149.6 ops/s | 157.2 ops/s | 🟢▲ +5.02% | 0.94% |
| burst_lockless/10 | iocp | ops_per_sec | 1.53K ops/s | 1.57K ops/s | 🟢▲ +2.38% | 0.37% |
| burst_lockless/100 | iocp | ops_per_sec | 151.9 ops/s | 160.0 ops/s | 🟢▲ +5.42% | 0.48% |
| concurrent/1 | iocp | ops_per_sec | 12.22K ops/s | 12.57K ops/s | 🟢▲ +2.71% | 1.41% |
| concurrent/16 | iocp | ops_per_sec | 13.22K ops/s | 13.47K ops/s | 🟢▲ +1.83% | 0.27% |
| concurrent/4 | iocp | ops_per_sec | 12.94K ops/s | 13.18K ops/s | 🟢▲ +1.84% | 0.28% |
| sequential | iocp | ops_per_sec | 12.25K ops/s | 12.47K ops/s | 🟢▲ +1.95% | 0.38% |
| sequential_lockless | iocp | ops_per_sec | 12.28K ops/s | 12.55K ops/s | 🟢▲ +2.19% | 0.32% |
fan_out
| Benchmark | Backend | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|
| concurrent_parents/1 | iocp | ops_per_sec | 7.30K ops/s | 7.35K ops/s | 🟢▲ +0.64% | 0.31% |
| concurrent_parents/16 | iocp | ops_per_sec | 6.32K ops/s | 6.21K ops/s | 🔴▼ -1.05% | 1.69% |
| concurrent_parents/4 | iocp | ops_per_sec | 6.87K ops/s | 6.91K ops/s | 🟢▲ +0.28% | 1.05% |
| concurrent_parents_lockless/1 | iocp | ops_per_sec | 7.32K ops/s | 7.35K ops/s | 🟢▲ +0.47% | 0.51% |
| concurrent_parents_lockless/16 | iocp | ops_per_sec | 6.40K ops/s | 6.36K ops/s | 🔴▼ -1.18% | 1.36% |
| concurrent_parents_lockless/4 | iocp | ops_per_sec | 6.90K ops/s | 6.95K ops/s | 🟢▲ +0.55% | 0.73% |
| fork_join/1 | iocp | ops_per_sec | 112.5K ops/s | 112.6K ops/s | 🟢▲ +0.05% | 0.68% |
| fork_join/16 | iocp | ops_per_sec | 7.31K ops/s | 7.34K ops/s | 🟢▲ +0.42% | 0.39% |
| fork_join/4 | iocp | ops_per_sec | 29.10K ops/s | 29.08K ops/s | 🟢▲ +0.02% | 0.41% |
| fork_join/64 | iocp | ops_per_sec | 1.72K ops/s | 1.74K ops/s | 🟢▲ +0.83% | 1.88% |
| fork_join_lockless/1 | iocp | ops_per_sec | 112.3K ops/s | 112.7K ops/s | 🟢▲ +0.19% | 0.65% |
| fork_join_lockless/16 | iocp | ops_per_sec | 7.31K ops/s | 7.34K ops/s | 🟢▲ +0.45% | 0.27% |
| fork_join_lockless/4 | iocp | ops_per_sec | 29.15K ops/s | 29.13K ops/s | 🟢▲ +0.12% | 0.47% |
| fork_join_lockless/64 | iocp | ops_per_sec | 1.73K ops/s | 1.74K ops/s | 🟢▲ +0.11% | 1.10% |
| nested/16 | iocp | ops_per_sec | 1.69K ops/s | 1.69K ops/s | 🔴▼ -0.33% | 1.45% |
| nested/4 | iocp | ops_per_sec | 7.12K ops/s | 7.14K ops/s | 🟢▲ +0.29% | 0.49% |
| nested_lockless/16 | iocp | ops_per_sec | 1.68K ops/s | 1.69K ops/s | 🔴▼ -0.64% | 1.38% |
| nested_lockless/4 | iocp | ops_per_sec | 7.11K ops/s | 7.15K ops/s | 🟢▲ +0.55% | 0.40% |
http_server
| Benchmark | Backend | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|
| concurrent/1 | iocp | ops_per_sec | 111.3K ops/s | 111.5K ops/s | 🟢▲ +0.15% | 0.44% |
| concurrent/16 | iocp | ops_per_sec | 108.4K ops/s | 108.6K ops/s | 🟢▲ +0.04% | 0.29% |
| concurrent/32 | iocp | ops_per_sec | 107.7K ops/s | 107.8K ops/s | 🟢▲ +0.15% | 0.30% |
| concurrent/4 | iocp | ops_per_sec | 109.3K ops/s | 109.1K ops/s | 🔴▼ -0.32% | 0.48% |
| multithread/1 | iocp | ops_per_sec | 107.5K ops/s | 107.7K ops/s | 🟢▲ +0.23% | 0.30% |
| multithread/16 | iocp | ops_per_sec | 267.0K ops/s | 265.6K ops/s | 🔴▼ -0.18% | 0.53% |
| multithread/2 | iocp | ops_per_sec | 181.5K ops/s | 181.2K ops/s | 🔴▼ -0.74% | 0.93% |
| multithread/4 | iocp | ops_per_sec | 225.6K ops/s | 224.4K ops/s | 🔴▼ -0.84% | 0.74% |
| multithread/8 | iocp | ops_per_sec | 267.4K ops/s | 266.0K ops/s | 🔴▼ -0.61% | 0.22% |
| single_conn | iocp | ops_per_sec | 111.6K ops/s | 111.5K ops/s | 🔴▼ -0.16% | 0.43% |
| single_conn_lockless | iocp | ops_per_sec | 111.8K ops/s | 111.7K ops/s | 🔴▼ -0.27% | 0.37% |
socket_latency
| Benchmark | Backend | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|
| concurrent/1 | iocp | latency_mean_ns | 7.60 µs | 7.55 µs | 🟢▲ +0.43% | 0.41% |
| concurrent/16 | iocp | latency_mean_ns | 130.91 µs | 130.62 µs | 🟢▲ +0.05% | 3.06% |
| concurrent/4 | iocp | latency_mean_ns | 30.54 µs | 30.43 µs | 🟢▲ +0.44% | 0.46% |
| concurrent_lockless/1 | iocp | latency_mean_ns | 7.60 µs | 7.57 µs | 🟢▲ +0.43% | 0.55% |
| concurrent_lockless/16 | iocp | latency_mean_ns | 123.01 µs | 121.85 µs | 🟢▲ +0.37% | 1.98% |
| concurrent_lockless/4 | iocp | latency_mean_ns | 30.48 µs | 30.48 µs | 🔴▼ -0.14% | 0.38% |
| pingpong/1 | iocp | latency_mean_ns | 7.58 µs | 7.55 µs | 🟢▲ +0.41% | 0.42% |
| pingpong/1024 | iocp | latency_mean_ns | 7.68 µs | 7.67 µs | 🟢▲ +0.20% | 0.54% |
| pingpong/64 | iocp | latency_mean_ns | 7.59 µs | 7.56 µs | 🟢▲ +0.41% | 0.26% |
| pingpong_lockless/1 | iocp | latency_mean_ns | 7.56 µs | 7.54 µs | 🟢▲ +0.09% | 0.45% |
| pingpong_lockless/1024 | iocp | latency_mean_ns | 7.69 µs | 7.68 µs | 🟢▲ +0.19% | 0.71% |
| pingpong_lockless/64 | iocp | latency_mean_ns | 7.59 µs | 7.56 µs | 🟢▲ +0.36% | 0.22% |
socket_throughput
| Benchmark | Backend | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|
| bidirectional/1024 | iocp | bytes_per_sec | 282.1 MB/s | 280.8 MB/s | 🔴▼ -0.66% | 0.63% |
| bidirectional/1048576 | iocp | bytes_per_sec | 5.27 GB/s | 5.47 GB/s | 🟢▲ +0.32% | 8.92% |
| bidirectional/16384 | iocp | bytes_per_sec | 3.70 GB/s | 3.75 GB/s | 🟢▲ +0.59% | 3.20% |
| bidirectional/262144 | iocp | bytes_per_sec | 9.26 GB/s | 9.59 GB/s | 🟢▲ +0.41% | 7.50% |
| bidirectional/4096 | iocp | bytes_per_sec | 1.08 GB/s | 1.08 GB/s | 🔴▼ -0.47% | 0.33% |
| bidirectional/65536 | iocp | bytes_per_sec | 8.78 GB/s | 9.09 GB/s | 🟢▲ +0.23% | 8.02% |
| bidirectional_lockless/1024 | iocp | bytes_per_sec | 281.7 MB/s | 280.4 MB/s | 🔴▼ -0.87% | 0.45% |
| bidirectional_lockless/1048576 | iocp | bytes_per_sec | 5.32 GB/s | 5.90 GB/s | 🟢▲ +10.15% | 9.06% |
| bidirectional_lockless/16384 | iocp | bytes_per_sec | 3.72 GB/s | 3.72 GB/s | 🔴▼ -0.20% | 0.91% |
| bidirectional_lockless/262144 | iocp | bytes_per_sec | 9.76 GB/s | 9.79 GB/s | 🟢▲ +0.45% | 2.63% |
| bidirectional_lockless/4096 | iocp | bytes_per_sec | 1.08 GB/s | 1.08 GB/s | 🔴▼ -0.33% | 0.28% |
| bidirectional_lockless/65536 | iocp | bytes_per_sec | 8.92 GB/s | 9.00 GB/s | 🟢▲ +1.16% | 1.96% |
| multithread/2 | iocp | bytes_per_sec | 12.77 GB/s | 12.81 GB/s | 🟢▲ +0.04% | 0.88% |
| multithread/4 | iocp | bytes_per_sec | 17.05 GB/s | 17.08 GB/s | 🔴▼ -0.17% | 1.38% |
| multithread/8 | iocp | bytes_per_sec | 18.35 GB/s | 18.39 GB/s | 🟢▲ +0.13% | 1.31% |
| unidirectional/1024 | iocp | bytes_per_sec | 285.3 MB/s | 285.5 MB/s | 🟢▲ +0.19% | 0.49% |
| unidirectional/1048576 | iocp | bytes_per_sec | 4.25 GB/s | 4.20 GB/s | 🔴▼ -4.16% | 7.56% |
| unidirectional/16384 | iocp | bytes_per_sec | 3.78 GB/s | 3.80 GB/s | 🟢▲ +0.96% | 1.18% |
| unidirectional/262144 | iocp | bytes_per_sec | 8.37 GB/s | 8.48 GB/s | 🔴▼ -1.55% | 12.91% |
| unidirectional/4096 | iocp | bytes_per_sec | 1.09 GB/s | 1.10 GB/s | 🟢▲ +0.64% | 0.52% |
| unidirectional/65536 | iocp | bytes_per_sec | 9.24 GB/s | 9.15 GB/s | 🟢▲ +1.09% | 4.13% |
| unidirectional_lockless/1024 | iocp | bytes_per_sec | 286.1 MB/s | 285.5 MB/s | 🔴▼ -0.04% | 0.47% |
| unidirectional_lockless/1048576 | iocp | bytes_per_sec | 4.78 GB/s | 4.82 GB/s | 🟢▲ +2.65% | 6.05% |
| unidirectional_lockless/16384 | iocp | bytes_per_sec | 3.80 GB/s | 3.80 GB/s | 🔴▼ -0.62% | 0.89% |
| unidirectional_lockless/262144 | iocp | bytes_per_sec | 9.79 GB/s | 9.81 GB/s | 🟢▲ +0.17% | 0.35% |
| unidirectional_lockless/4096 | iocp | bytes_per_sec | 1.10 GB/s | 1.10 GB/s | 🔴▼ -0.11% | 0.41% |
| unidirectional_lockless/65536 | iocp | bytes_per_sec | 9.26 GB/s | 9.32 GB/s | 🟢▲ +0.69% | 1.80% |
macos — full results (113 benchmarks, 5 iterations, 1.5s each)
accept_churn
| Benchmark | Backend | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|
| burst/10 | kqueue | ops_per_sec | 4.21K ops/s | 4.33K ops/s | 🟢▲ +2.75% | 0.88% |
| burst/100 | kqueue | ops_per_sec | 433.7 ops/s | 443.4 ops/s | 🟢▲ +3.34% | 1.14% |
| burst_lockless/10 | kqueue | ops_per_sec | 4.27K ops/s | 4.37K ops/s | 🟢▲ +2.50% | 0.57% |
| burst_lockless/100 | kqueue | ops_per_sec | 434.8 ops/s | 446.9 ops/s | 🟢▲ +2.53% | 1.09% |
| concurrent/1 | kqueue | ops_per_sec | 19.66K ops/s | 20.00K ops/s | 🟢▲ +1.35% | 0.86% |
| concurrent/16 | kqueue | ops_per_sec | 35.19K ops/s | 36.38K ops/s | 🟢▲ +3.44% | 0.95% |
| concurrent/4 | kqueue | ops_per_sec | 29.41K ops/s | 29.38K ops/s | 🔴▼ -0.64% | 1.09% |
| sequential | kqueue | ops_per_sec | 19.96K ops/s | 20.27K ops/s | 🟢▲ +2.06% | 0.75% |
| sequential_lockless | kqueue | ops_per_sec | 20.02K ops/s | 20.26K ops/s | 🟢▲ +0.50% | 1.43% |
fan_out
| Benchmark | Backend | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|
| concurrent_parents/1 | kqueue | ops_per_sec | 8.04K ops/s | 8.08K ops/s | 🟢▲ +0.31% | 0.46% |
| concurrent_parents/16 | kqueue | ops_per_sec | 8.05K ops/s | 6.48K ops/s | 🔴▼ -27.75% | 17.85% |
| concurrent_parents/4 | kqueue | ops_per_sec | 8.15K ops/s | 8.29K ops/s | 🟢▲ +2.78% | 1.25% |
| concurrent_parents_lockless/1 | kqueue | ops_per_sec | 8.11K ops/s | 8.18K ops/s | 🟢▲ +0.93% | 0.76% |
| concurrent_parents_lockless/16 | kqueue | ops_per_sec | 8.04K ops/s | 7.09K ops/s | 🔴▼ -0.41% | 20.12% |
| concurrent_parents_lockless/4 | kqueue | ops_per_sec | 8.21K ops/s | 8.36K ops/s | 🟢▲ +2.90% | 1.33% |
| fork_join/1 | kqueue | ops_per_sec | 47.79K ops/s | 48.09K ops/s | 🟢▲ +0.96% | 0.90% |
| fork_join/16 | kqueue | ops_per_sec | 8.04K ops/s | 8.04K ops/s | 🔴▼ -0.02% | 0.32% |
| fork_join/4 | kqueue | ops_per_sec | 23.54K ops/s | 23.65K ops/s | 🟢▲ +0.60% | 0.42% |
| fork_join/64 | kqueue | ops_per_sec | 2.07K ops/s | 2.05K ops/s | 🔴▼ -0.34% | 1.91% |
| fork_join_lockless/1 | kqueue | ops_per_sec | 49.51K ops/s | 49.50K ops/s | 🔴▼ -0.06% | 0.38% |
| fork_join_lockless/16 | kqueue | ops_per_sec | 8.17K ops/s | 8.13K ops/s | 🔴▼ -0.40% | 0.79% |
| fork_join_lockless/4 | kqueue | ops_per_sec | 23.48K ops/s | 23.63K ops/s | 🟢▲ +0.88% | 0.71% |
| fork_join_lockless/64 | kqueue | ops_per_sec | 2.09K ops/s | 2.08K ops/s | 🟢▲ +0.13% | 1.99% |
| nested/16 | kqueue | ops_per_sec | 2.03K ops/s | 2.04K ops/s | 🟢▲ +0.22% | 1.87% |
| nested/4 | kqueue | ops_per_sec | 7.93K ops/s | 7.96K ops/s | 🟢▲ +0.09% | 0.34% |
| nested_lockless/16 | kqueue | ops_per_sec | 2.02K ops/s | 2.07K ops/s | 🟢▲ +3.78% | 1.86% |
| nested_lockless/4 | kqueue | ops_per_sec | 8.03K ops/s | 8.06K ops/s | 🟢▲ +0.26% | 0.52% |
http_server
| Benchmark | Backend | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|
| concurrent/1 | kqueue | ops_per_sec | 49.36K ops/s | 49.14K ops/s | 🔴▼ -0.43% | 0.69% |
| concurrent/16 | kqueue | ops_per_sec | 129.8K ops/s | 129.0K ops/s | 🔴▼ -0.57% | 0.41% |
| concurrent/32 | kqueue | ops_per_sec | 129.9K ops/s | 128.2K ops/s | 🔴▼ -1.72% | 0.83% |
| concurrent/4 | kqueue | ops_per_sec | 88.76K ops/s | 89.93K ops/s | 🟢▲ +1.40% | 0.28% |
| multithread/1 | kqueue | ops_per_sec | 130.1K ops/s | 128.0K ops/s | 🔴▼ -1.74% | 1.23% |
| multithread/16 | kqueue | ops_per_sec | 135.7K ops/s | 133.4K ops/s | 🟢▲ +0.30% | 4.64% |
| multithread/2 | kqueue | ops_per_sec | 182.8K ops/s | 185.0K ops/s | 🟢▲ +1.32% | 0.42% |
| multithread/4 | kqueue | ops_per_sec | 165.0K ops/s | 162.2K ops/s | 🔴▼ -0.53% | 3.38% |
| multithread/8 | kqueue | ops_per_sec | 141.9K ops/s | 136.9K ops/s | 🔴▼ -1.91% | 3.68% |
| single_conn | kqueue | ops_per_sec | 49.43K ops/s | 49.03K ops/s | 🔴▼ -0.67% | 0.47% |
| single_conn_lockless | kqueue | ops_per_sec | 49.54K ops/s | 49.22K ops/s | 🔴▼ -0.59% | 0.56% |
local_socket_latency
| Benchmark | Backend | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|
| concurrent/1 | kqueue | latency_mean_ns | 1.84 µs | 1.85 µs | 🔴▼ -0.63% | 0.43% |
| concurrent/16 | kqueue | latency_mean_ns | 27.16 µs | 27.32 µs | 🔴▼ -0.58% | 0.37% |
| concurrent/4 | kqueue | latency_mean_ns | 6.83 µs | 6.87 µs | 🔴▼ -0.66% | 0.45% |
| concurrent_lockless/1 | kqueue | latency_mean_ns | 1.82 µs | 1.84 µs | 🔴▼ -0.48% | 0.42% |
| concurrent_lockless/16 | kqueue | latency_mean_ns | 26.96 µs | 27.10 µs | 🔴▼ -0.60% | 0.32% |
| concurrent_lockless/4 | kqueue | latency_mean_ns | 6.78 µs | 6.82 µs | 🔴▼ -0.56% | 0.38% |
| pingpong/1 | kqueue | latency_mean_ns | 1.83 µs | 1.85 µs | 🔴▼ -0.91% | 0.32% |
| pingpong/1024 | kqueue | latency_mean_ns | 1.93 µs | 1.94 µs | 🔴▼ -0.62% | 0.35% |
| pingpong/64 | kqueue | latency_mean_ns | 1.83 µs | 1.85 µs | 🔴▼ -0.82% | 0.38% |
| pingpong_lockless/1 | kqueue | latency_mean_ns | 1.82 µs | 1.84 µs | 🔴▼ -0.84% | 0.51% |
| pingpong_lockless/1024 | kqueue | latency_mean_ns | 1.92 µs | 1.93 µs | 🔴▼ -0.68% | 0.40% |
| pingpong_lockless/64 | kqueue | latency_mean_ns | 1.82 µs | 1.84 µs | 🔴▼ -0.96% | 0.38% |
local_socket_throughput
| Benchmark | Backend | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|
| bidirectional/1024 | kqueue | bytes_per_sec | 1.30 GB/s | 1.30 GB/s | 🔴▼ -0.51% | 0.29% |
| bidirectional/1048576 | kqueue | bytes_per_sec | 3.83 GB/s | 3.84 GB/s | 🟢▲ +0.36% | 0.58% |
| bidirectional/16384 | kqueue | bytes_per_sec | 3.80 GB/s | 3.82 GB/s | 🟢▲ +0.63% | 0.69% |
| bidirectional/262144 | kqueue | bytes_per_sec | 3.83 GB/s | 3.82 GB/s | 🔴▼ -0.13% | 0.71% |
| bidirectional/4096 | kqueue | bytes_per_sec | 2.89 GB/s | 2.90 GB/s | 🟢▲ +0.32% | 0.58% |
| bidirectional/65536 | kqueue | bytes_per_sec | 3.82 GB/s | 3.82 GB/s | 🔴▼ -0.25% | 0.33% |
| bidirectional_lockless/1024 | kqueue | bytes_per_sec | 1.31 GB/s | 1.30 GB/s | 🔴▼ -0.39% | 0.28% |
| bidirectional_lockless/1048576 | kqueue | bytes_per_sec | 3.87 GB/s | 3.90 GB/s | 🟢▲ +0.89% | 0.63% |
| bidirectional_lockless/16384 | kqueue | bytes_per_sec | 3.87 GB/s | 3.90 GB/s | 🟢▲ +0.80% | 0.49% |
| bidirectional_lockless/262144 | kqueue | bytes_per_sec | 3.89 GB/s | 3.89 GB/s | 🟢▲ +0.12% | 0.60% |
| bidirectional_lockless/4096 | kqueue | bytes_per_sec | 2.94 GB/s | 2.94 GB/s | 🟢▲ +0.55% | 0.47% |
| bidirectional_lockless/65536 | kqueue | bytes_per_sec | 3.90 GB/s | 3.90 GB/s | 🔴▼ -0.03% | 1.03% |
| unidirectional/1024 | kqueue | bytes_per_sec | 1.28 GB/s | 1.27 GB/s | 🔴▼ -0.03% | 0.56% |
| unidirectional/1048576 | kqueue | bytes_per_sec | 3.46 GB/s | 3.45 GB/s | 🔴▼ -0.13% | 0.42% |
| unidirectional/16384 | kqueue | bytes_per_sec | 3.46 GB/s | 3.46 GB/s | 🟢▲ +0.25% | 0.53% |
| unidirectional/262144 | kqueue | bytes_per_sec | 3.45 GB/s | 3.45 GB/s | 🔴▼ -0.04% | 0.31% |
| unidirectional/4096 | kqueue | bytes_per_sec | 2.68 GB/s | 2.68 GB/s | 🔴▼ -0.21% | 0.55% |
| unidirectional/65536 | kqueue | bytes_per_sec | 3.45 GB/s | 3.46 GB/s | 🟢▲ +0.33% | 0.48% |
| unidirectional_lockless/1024 | kqueue | bytes_per_sec | 1.28 GB/s | 1.28 GB/s | 🔴▼ -0.40% | 0.41% |
| unidirectional_lockless/1048576 | kqueue | bytes_per_sec | 3.51 GB/s | 3.50 GB/s | 🔴▼ -0.09% | 0.40% |
| unidirectional_lockless/16384 | kqueue | bytes_per_sec | 3.52 GB/s | 3.51 GB/s | 🔴▼ -0.43% | 0.36% |
| unidirectional_lockless/262144 | kqueue | bytes_per_sec | 3.50 GB/s | 3.52 GB/s | 🟢▲ +0.52% | 0.47% |
| unidirectional_lockless/4096 | kqueue | bytes_per_sec | 2.71 GB/s | 2.71 GB/s | 🔴▼ -0.10% | 0.28% |
| unidirectional_lockless/65536 | kqueue | bytes_per_sec | 3.51 GB/s | 3.51 GB/s | 🔴▼ -0.28% | 0.50% |
socket_latency
| Benchmark | Backend | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|
| concurrent/1 | kqueue | latency_mean_ns | 18.85 µs | 18.93 µs | 🔴▼ -0.51% | 0.37% |
| concurrent/16 | kqueue | latency_mean_ns | 119.90 µs | 120.50 µs | 🔴▼ -0.64% | 0.47% |
| concurrent/4 | kqueue | latency_mean_ns | 43.61 µs | 43.46 µs | 🔴▼ -0.07% | 1.23% |
| concurrent_lockless/1 | kqueue | latency_mean_ns | 18.78 µs | 18.86 µs | 🔴▼ -0.29% | 0.29% |
| concurrent_lockless/16 | kqueue | latency_mean_ns | 120.30 µs | 119.63 µs | 🟢▲ +1.15% | 0.88% |
| concurrent_lockless/4 | kqueue | latency_mean_ns | 43.08 µs | 42.75 µs | 🟢▲ +1.04% | 0.80% |
| pingpong/1 | kqueue | latency_mean_ns | 15.51 µs | 15.50 µs | 🔴▼ -0.07% | 1.59% |
| pingpong/1024 | kqueue | latency_mean_ns | 18.98 µs | 19.10 µs | 🔴▼ -0.02% | 1.45% |
| pingpong/64 | kqueue | latency_mean_ns | 18.85 µs | 18.94 µs | 🔴▼ -0.19% | 0.56% |
| pingpong_lockless/1 | kqueue | latency_mean_ns | 15.40 µs | 15.40 µs | 🟢▲ +0.09% | 0.16% |
| pingpong_lockless/1024 | kqueue | latency_mean_ns | 19.08 µs | 19.10 µs | 🔴▼ -0.06% | 0.36% |
| pingpong_lockless/64 | kqueue | latency_mean_ns | 18.80 µs | 18.84 µs | 🔴▼ -0.30% | 0.28% |
socket_throughput
| Benchmark | Backend | Metric | Base | Head | Δ | Noise |
|---|---|---|---|---|---|---|
| bidirectional/1024 | kqueue | bytes_per_sec | 470.2 MB/s | 469.8 MB/s | 🔴▼ -0.05% | 1.03% |
| bidirectional/1048576 | kqueue | bytes_per_sec | 7.86 GB/s | 7.67 GB/s | 🔴▼ -1.45% | 4.35% |
| bidirectional/16384 | kqueue | bytes_per_sec | 4.51 GB/s | 4.54 GB/s | 🟢▲ +0.81% | 0.64% |
| bidirectional/262144 | kqueue | bytes_per_sec | 8.82 GB/s | 8.69 GB/s | 🔴▼ -1.58% | 2.25% |
| bidirectional/4096 | kqueue | bytes_per_sec | 1.80 GB/s | 1.81 GB/s | 🟢▲ +0.70% | 1.08% |
| bidirectional/65536 | kqueue | bytes_per_sec | 7.49 GB/s | 7.59 GB/s | 🟢▲ +0.01% | 1.78% |
| bidirectional_lockless/1024 | kqueue | bytes_per_sec | 471.6 MB/s | 473.8 MB/s | 🟢▲ +0.54% | 0.92% |
| bidirectional_lockless/1048576 | kqueue | bytes_per_sec | 7.87 GB/s | 7.63 GB/s | 🔴▼ -1.71% | 3.92% |
| bidirectional_lockless/16384 | kqueue | bytes_per_sec | 4.57 GB/s | 4.58 GB/s | 🟢▲ +0.89% | 1.67% |
| bidirectional_lockless/262144 | kqueue | bytes_per_sec | 8.86 GB/s | 8.77 GB/s | 🔴▼ -0.21% | 1.85% |
| bidirectional_lockless/4096 | kqueue | bytes_per_sec | 1.82 GB/s | 1.81 GB/s | 🔴▼ -0.48% | 0.63% |
| bidirectional_lockless/65536 | kqueue | bytes_per_sec | 7.54 GB/s | 7.61 GB/s | 🟢▲ +0.48% | 1.69% |
| multithread/2 | kqueue | bytes_per_sec | 7.60 GB/s | 7.61 GB/s | 🟢▲ +1.85% | 4.11% |
| multithread/4 | kqueue | bytes_per_sec | 3.67 GB/s | 3.78 GB/s | 🟢▲ +5.71% | 3.11% |
| multithread/8 | kqueue | bytes_per_sec | 3.22 GB/s | 3.43 GB/s | 🟢▲ +10.20% | 11.96% |
| unidirectional/1024 | kqueue | bytes_per_sec | 455.3 MB/s | 453.4 MB/s | 🟢▲ +0.39% | 1.71% |
| unidirectional/1048576 | kqueue | bytes_per_sec | 9.03 GB/s | 8.78 GB/s | 🔴▼ -1.02% | 5.39% |
| unidirectional/16384 | kqueue | bytes_per_sec | 4.46 GB/s | 4.46 GB/s | 🔴▼ -0.04% | 1.85% |
| unidirectional/262144 | kqueue | bytes_per_sec | 8.92 GB/s | 8.90 GB/s | 🟢▲ +0.47% | 1.70% |
| unidirectional/4096 | kqueue | bytes_per_sec | 1.79 GB/s | 1.78 GB/s | 🟢▲ +0.09% | 1.49% |
| unidirectional/65536 | kqueue | bytes_per_sec | 7.37 GB/s | 7.38 GB/s | 🟢▲ +0.15% | 2.48% |
| unidirectional_lockless/1024 | kqueue | bytes_per_sec | 472.8 MB/s | 472.0 MB/s | 🔴▼ -0.04% | 1.98% |
| unidirectional_lockless/1048576 | kqueue | bytes_per_sec | 9.02 GB/s | 8.87 GB/s | 🔴▼ -0.57% | 5.13% |
| unidirectional_lockless/16384 | kqueue | bytes_per_sec | 4.48 GB/s | 4.47 GB/s | 🔴▼ -0.40% | 2.17% |
| unidirectional_lockless/262144 | kqueue | bytes_per_sec | 8.89 GB/s | 8.93 GB/s | 🟢▲ +0.46% | 2.30% |
| unidirectional_lockless/4096 | kqueue | bytes_per_sec | 1.79 GB/s | 1.80 GB/s | 🟢▲ +0.53% | 2.31% |
| unidirectional_lockless/65536 | kqueue | bytes_per_sec | 7.34 GB/s | 7.42 GB/s | 🟢▲ +2.18% | 1.50% |
Run & raw JSON artifacts · flag rule: |median Δ| > max(2%, 3×CV of the noisier side) · advisory only
Opening and closing sockets, acceptors, timers, files, resolvers and signal sets allocated and freed an implementation each time, and accepting, random-access file I/O and launching a tcp_server connection allocated per operation. Implementations now come from per-type object pools and are held through counted object_ref handles, so an operation in flight keeps its object alive. Accept nodes, random-access file operations and connection launches are recycled, multishot accept hands its nodes to the kernel, and the IOCP wait reactor reuses its drain buffers, so steady-state I/O no longer allocates. Tests poison recycled implementations, churn them, and check that steady-state operations do not allocate. The fault harness chains its shadows into the sanitizer interceptors.
sgerbino
force-pushed
the
pr/lifetime-executor
branch
from
October 16, 2026 16:54
2669b45 to
b173ee3
Compare
|
An automated preview of the documentation is available at https://395.corosio.prtest3.cppalliance.org/index.html If more commits are pushed to the pull request, the docs will rebuild at the same URL. 2026-10-16 17:39:29 UTC |
An awaiter is resumed through the continuation its awaitable holds, on its own context rather than the one that completed it. A file keeps its descriptor number allocated while a pool worker uses it, and adopting a descriptor is refused in the unsafe locking tier. Timers shut down before the scheduler drains, a drain's writes are ordered before a lock-free cancel trusts them, a stop request on another thread can race timer teardown, and timeout()'s detached timer coroutine is allocated outside the awaiting chain. Signals are delivered outside the signal pipe's lock. A TLS stream can be destroyed or moved with an operation in flight, and a wolfSSL shutdown finishes when its close_notify arrives behind another record. An accepted peer whose awaiter never resumes is closed, including one a drained reactor accept already took. A socket or mocket pair whose connect is refused fails.
A pending connect is cancelled when its socket is released, and an acceptor keeps listening after cancel(). Cancel requests target only the object's own operations and are never dropped, an operation whose stop lands before its SQE is linked is cancelled, and a wait cancelled by close skips the SO_ERROR probe. A post from another thread under unsafe_io wakes the run thread, and run_for is bounded by its duration when a later timer is armed.
Socket cancellation is re-checked before an operation can complete, and connects and lookups stopped before they are issued are cancelled. An object handle's wait is reserved atomically and its stop callback engaged before it is published. An accept's peer is constructed before the accept is armed, the local acceptor's close is defined in every local socket translation unit, and sockets in skip-on-success mode are refused for adoption. The wait reactor skips the SO_ERROR probe for a closed socket, ends a wait whose stop lands while it registers, and no longer has cancels queued before it runs. Shutdown sweeps the port past the stop signal, and signal-wait completions are posted instead of resumed inline.
A tcp_server can be moved or destroyed while it runs, a connection launched after stop() is stopped, and set_workers is refused while a worker is in use. A worker stays out of the pool until its run() returns, and a connection is allocated outside the chain that launches it. The documentation says what an exception from a worker's run() does and that the server binds only while no session is active.
Destroying an io_context left coroutines suspended in its operations, timers, signal waits, blocking-pool work and queues suspended forever, with their frames and everything they held leaked. Each holder now gives a continuation it will never resume to capy::abandon, which unwinds the coroutine's chain from its owner on the owner's executor: reactor, io_uring and IOCP operations, timers, signal waits, resolver and file work on the blocking pool, posted work, and tcp_server connections and workers. Schedulers finish with themselves before work posted to them can run, wait for cancellations still posting before they drain, destroy work posted after the drain, and stop under their lock. A lockless io_uring context can be torn down from any thread. Select is woken before the lock an operation parked under is released, and posting a ready reactor operation is its initiator's last touch. Blocking-pool operations count as work on the context that owns them, and a run call restores the thread's frame allocator. A completed operation whose executor throws terminates. tcp_server holds work on a connection's context until it ends, returns workers when that context is torn down, gives back a launch whose post throws, and transfers from its launch coroutine as a task does. Socket and mocket pairs finish their setup before returning or throwing. Teardown tests run under AddressSanitizer, and the documentation states what io_context teardown destroys and the order between contexts.
One page now says how long I/O objects, buffers and contexts must live, how to stop work, what destroying a context does to coroutines still suspended in it, why work must not cross contexts at teardown, and what happens when an executor throws as an operation completes. It ends with a checklist for code that suspends and resumes coroutines, covering the ways such code can break teardown.
sgerbino
force-pushed
the
pr/lifetime-executor
branch
from
October 16, 2026 17:33
b173ee3 to
dbb0bed
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
io_contextleaves the coroutines suspended in it suspended forever. That covers operations, timers, signal waits, blocking-pool work and queued work. Their frames, and the I/O objects in them, leak.Teardown
capy::abandon. The chain then unwinds from its owner, on the owner's executor. Destructors run, and no code after a suspension point runs.std::terminate. Nothing else could resume the coroutine or unwind it.Pools
Fixes
run_for.Documentation
doc/design/lifetime-contract.md, sets out when an implementation may be touched and when its memory may be reused.Testing
Teardown tests run under ASan and LSan, and the full CI matrix is green. Commits before the teardown commit build, but their tests need the matching capy.
Resolves #380
Resolves #381
Resolves #384
Resolves #385
Resolves #390
Resolves #391
Resolves #392