Linux Benchmarks

Generated 2026-11-06 from corosio 0b3830d5c30b — benchmark run. This page is fully generated; do not edit by hand (see the Benchmarks landing page).

Summary

Within noise means the relative difference is within twice the combined run-to-run noise (the root-sum-square of each side’s CV). Differences that small are indistinguishable from measurement jitter. See Methodology for how these figures are computed.

io_uring

58 faster · 48 within noise · 7 slower of 113 benchmarks — median +2.9% vs Boost.Asio (callbacks) on the same reactor.

Summary (io_uring) — Linux ← slower · within noise · faster → per benchmark, vs Boost.Asio (callbacks) local_socket_latency 12 benchmarks faster than asio (callbacks) 12 +28.4% socket_latency 1 benchmark within noise than asio (callbacks) 11 benchmarks faster than asio (callbacks) 11 +15.9% socket_throughput 9 benchmarks within noise than asio (callbacks) 9 18 benchmarks faster than asio (callbacks) 18 +8.9% http_server 4 benchmarks within noise than asio (callbacks) 4 7 benchmarks faster than asio (callbacks) 7 +2.5% fan_out 1 benchmark slower than asio (callbacks) 17 benchmarks within noise than asio (callbacks) 17 +1.0% accept_churn 2 benchmarks slower than asio (callbacks) 7 benchmarks within noise than asio (callbacks) 7 -0.7% local_socket_throughput 4 benchmarks slower than asio (callbacks) 4 10 benchmarks within noise than asio (callbacks) 10 10 benchmarks faster than asio (callbacks) 10 -1.8%

epoll

31 faster · 35 within noise · 47 slower of 113 benchmarks — median -1.0% vs Boost.Asio (callbacks) on the same reactor.

Summary (epoll) — Linux ← slower · within noise · faster → per benchmark, vs Boost.Asio (callbacks) local_socket_latency 4 benchmarks slower than asio (callbacks) 4 3 benchmarks within noise than asio (callbacks) 3 5 benchmarks faster than asio (callbacks) 5 +10.3% socket_latency 2 benchmarks slower than asio (callbacks) 2 2 benchmarks within noise than asio (callbacks) 2 8 benchmarks faster than asio (callbacks) 8 +4.9% socket_throughput 5 benchmarks slower than asio (callbacks) 5 9 benchmarks within noise than asio (callbacks) 9 13 benchmarks faster than asio (callbacks) 13 +2.5% local_socket_throughput 4 benchmarks slower than asio (callbacks) 4 15 benchmarks within noise than asio (callbacks) 15 5 benchmarks faster than asio (callbacks) 5 +1.1% accept_churn 5 benchmarks slower than asio (callbacks) 5 4 benchmarks within noise than asio (callbacks) 4 -4.0% http_server 9 benchmarks slower than asio (callbacks) 9 2 benchmarks within noise than asio (callbacks) 2 -4.1% fan_out 18 benchmarks slower than asio (callbacks) 18 -6.5%

Test Environment

CPU

AMD EPYC 7302P 16-Core Processor

Cores

4

RAM (GB)

31

OS

Linux 7.0.0-34-generic

Kernel/build

#34-Ubuntu SMP PREEMPT_DYNAMIC Wed Sep 2 14:29:37 UTC 2026

Compiler

c++ (Ubuntu 15.2.0-16ubuntu1) 15.2.0

CMake

cmake version 4.2.3

liburing

2.14-1

Boost commit

b6d874b77b75085a1b35c640a76d37ab8cd9bb97

Asio commit

e99d9da6d9b76a222e29dcaf3d2df51c788b7527

Asio reactor

epoll and io_uring (matched per configuration)

Capy commit

bdadc6adef8c8eb79da6454373175bb1428be524

Corosio commit

0b3830d5c30b96e4a95c0248953575ba7ffcd4d1

Corosio branch

develop

Date (UTC)

2026-11-06

Iterations

7

Duration per benchmark (s)

2.0

Results

accept_churn

Rate of setting up and tearing down short-lived TCP connections: connect, accept, close.

io_uring

accept_churn (io_uring) — Linux ↑ faster · dotted line = asio (callbacks) · backend = io_uring corosio asio (coroutines) -6% -4% -2% +2% 0% burst/10 — N connects are fired at once, then all N are accepted before closing; N is the burst size. burst/10 — N connects are fired at once, then all N are accepted before closing; N is the burst size. burst/10 burst/100 — N connects are fired at once, then all N are accepted before closing; N is the burst size. burst/100 — N connects are fired at once, then all N are accepted before closing; N is the burst size. +0% burst/100 burst_lockless/10 — Same as burst, with the context in single-threaded lockless mode; N is the burst size. burst_lockless/10 — Same as burst, with the context in single-threaded lockless mode; N is the burst size. burst_lockless/10 burst_lockless/100 — Same as burst, with the context in single-threaded lockless mode; N is the burst size. burst_lockless/100 — Same as burst, with the context in single-threaded lockless mode; N is the burst size. burst_lockless/100 concurrent/1 — N independent accept loops run on separate listeners at once, each doing a one-way one-byte transfer (client writes, server reads) per connection; N is the number of loops. concurrent/1 — N independent accept loops run on separate listeners at once, each doing a one-way one-byte transfer (client writes, server reads) per connection; N is the number of loops. concurrent/1 concurrent/16 — N independent accept loops run on separate listeners at once, each doing a one-way one-byte transfer (client writes, server reads) per connection; N is the number of loops. concurrent/16 — N independent accept loops run on separate listeners at once, each doing a one-way one-byte transfer (client writes, server reads) per connection; N is the number of loops. concurrent/16 concurrent/4 — N independent accept loops run on separate listeners at once, each doing a one-way one-byte transfer (client writes, server reads) per connection; N is the number of loops. -3% concurrent/4 — N independent accept loops run on separate listeners at once, each doing a one-way one-byte transfer (client writes, server reads) per connection; N is the number of loops. concurrent/4 sequential — Single connect/accept/close loop with a one-way one-byte transfer (client writes, server reads) per connection, one connection at a time. +0% sequential — Single connect/accept/close loop with a one-way one-byte transfer (client writes, server reads) per connection, one connection at a time. sequential sequential_lockless — Same as sequential, with the context in single-threaded lockless mode. sequential_lockless — Same as sequential, with the context in single-threaded lockless mode. -2% sequential_lockless
Detailed results
Benchmark Implementation Median CV vs asio

burst/10

corosio (io_uring)

2.40K ops/s

0.48%

-0.5%

burst/10

asio (coroutines, io_uring)

2.39K ops/s

1.09%

-0.8%

burst/10

asio (callbacks, io_uring)

2.41K ops/s

0.09%

baseline (io_uring)

burst/100

corosio (io_uring)

246.4 ops/s

0.66%

-0.2%

burst/100

asio (coroutines, io_uring)

247.9 ops/s

0.97%

+0.4%

burst/100

asio (callbacks, io_uring)

246.9 ops/s

0.64%

baseline (io_uring)

burst_lockless/10

corosio (io_uring)

2.40K ops/s

0.28%

-0.8%

burst_lockless/10

asio (coroutines, io_uring)

2.40K ops/s

1.09%

-0.9%

burst_lockless/10

asio (callbacks, io_uring)

2.42K ops/s

0.40%

baseline (io_uring)

burst_lockless/100

corosio (io_uring)

247.3 ops/s

0.68%

-1.0%

burst_lockless/100

asio (coroutines, io_uring)

249.0 ops/s

1.00%

-0.3%

burst_lockless/100

asio (callbacks, io_uring)

249.8 ops/s

0.65%

baseline (io_uring)

concurrent/1

corosio (io_uring)

17.12K ops/s

1.66%

-0.7%

concurrent/1

asio (coroutines, io_uring)

16.88K ops/s

1.18%

-2.1%

concurrent/1

asio (callbacks, io_uring)

17.25K ops/s

0.36%

baseline (io_uring)

concurrent/16

corosio (io_uring)

18.83K ops/s

1.06%

-2.4%

concurrent/16

asio (coroutines, io_uring)

19.05K ops/s

1.16%

-1.2%

concurrent/16

asio (callbacks, io_uring)

19.28K ops/s

0.12%

baseline (io_uring)

concurrent/4

corosio (io_uring)

17.88K ops/s

1.24%

-3.2%

concurrent/4

asio (coroutines, io_uring)

18.15K ops/s

1.11%

-1.7%

concurrent/4

asio (callbacks, io_uring)

18.47K ops/s

0.21%

baseline (io_uring)

sequential

corosio (io_uring)

17.23K ops/s

1.25%

+0.0%

sequential

asio (coroutines, io_uring)

16.86K ops/s

1.41%

-2.2%

sequential

asio (callbacks, io_uring)

17.23K ops/s

0.27%

baseline (io_uring)

sequential_lockless

corosio (io_uring)

17.37K ops/s

1.21%

-0.1%

sequential_lockless

asio (coroutines, io_uring)

17.00K ops/s

1.33%

-2.3%

sequential_lockless

asio (callbacks, io_uring)

17.39K ops/s

0.16%

baseline (io_uring)

epoll

accept_churn (epoll) — Linux ↑ faster · dotted line = asio (callbacks) · backend = epoll corosio asio (coroutines) -10% -5% +5% 0% burst/10 — N connects are fired at once, then all N are accepted before closing; N is the burst size. -7% burst/10 — N connects are fired at once, then all N are accepted before closing; N is the burst size. -4% burst/10 burst/100 — N connects are fired at once, then all N are accepted before closing; N is the burst size. burst/100 — N connects are fired at once, then all N are accepted before closing; N is the burst size. burst/100 burst_lockless/10 — Same as burst, with the context in single-threaded lockless mode; N is the burst size. burst_lockless/10 — Same as burst, with the context in single-threaded lockless mode; N is the burst size. burst_lockless/10 burst_lockless/100 — Same as burst, with the context in single-threaded lockless mode; N is the burst size. burst_lockless/100 — Same as burst, with the context in single-threaded lockless mode; N is the burst size. burst_lockless/100 concurrent/1 — N independent accept loops run on separate listeners at once, each doing a one-way one-byte transfer (client writes, server reads) per connection; N is the number of loops. concurrent/1 — N independent accept loops run on separate listeners at once, each doing a one-way one-byte transfer (client writes, server reads) per connection; N is the number of loops. concurrent/1 concurrent/16 — N independent accept loops run on separate listeners at once, each doing a one-way one-byte transfer (client writes, server reads) per connection; N is the number of loops. concurrent/16 — N independent accept loops run on separate listeners at once, each doing a one-way one-byte transfer (client writes, server reads) per connection; N is the number of loops. -2% concurrent/16 concurrent/4 — N independent accept loops run on separate listeners at once, each doing a one-way one-byte transfer (client writes, server reads) per connection; N is the number of loops. concurrent/4 — N independent accept loops run on separate listeners at once, each doing a one-way one-byte transfer (client writes, server reads) per connection; N is the number of loops. concurrent/4 sequential — Single connect/accept/close loop with a one-way one-byte transfer (client writes, server reads) per connection, one connection at a time. +1% sequential — Single connect/accept/close loop with a one-way one-byte transfer (client writes, server reads) per connection, one connection at a time. sequential sequential_lockless — Same as sequential, with the context in single-threaded lockless mode. sequential_lockless — Same as sequential, with the context in single-threaded lockless mode. sequential_lockless
Detailed results
Benchmark Implementation Median CV vs asio

burst/10

corosio (epoll)

2.00K ops/s

0.80%

-6.7%

burst/10

asio (coroutines, epoll)

2.05K ops/s

0.95%

-4.3%

burst/10

asio (callbacks, epoll)

2.14K ops/s

0.88%

baseline (epoll)

burst/100

corosio (epoll)

202.4 ops/s

0.75%

-6.3%

burst/100

asio (coroutines, epoll)

209.0 ops/s

0.94%

-3.3%

burst/100

asio (callbacks, epoll)

216.0 ops/s

0.89%

baseline (epoll)

burst_lockless/10

corosio (epoll)

2.02K ops/s

0.71%

-5.8%

burst_lockless/10

asio (coroutines, epoll)

2.06K ops/s

0.16%

-4.0%

burst_lockless/10

asio (callbacks, epoll)

2.15K ops/s

0.58%

baseline (epoll)

burst_lockless/100

corosio (epoll)

204.4 ops/s

0.77%

-5.9%

burst_lockless/100

asio (coroutines, epoll)

210.3 ops/s

0.32%

-3.1%

burst_lockless/100

asio (callbacks, epoll)

217.2 ops/s

0.94%

baseline (epoll)

concurrent/1

corosio (epoll)

15.81K ops/s

0.67%

+0.8%

concurrent/1

asio (coroutines, epoll)

15.24K ops/s

1.02%

-2.9%

concurrent/1

asio (callbacks, epoll)

15.68K ops/s

0.99%

baseline (epoll)

concurrent/16

corosio (epoll)

15.81K ops/s

0.87%

-4.0%

concurrent/16

asio (coroutines, epoll)

16.13K ops/s

1.06%

-2.1%

concurrent/16

asio (callbacks, epoll)

16.47K ops/s

1.12%

baseline (epoll)

concurrent/4

corosio (epoll)

15.81K ops/s

0.83%

-1.9%

concurrent/4

asio (coroutines, epoll)

15.70K ops/s

0.97%

-2.6%

concurrent/4

asio (callbacks, epoll)

16.12K ops/s

1.04%

baseline (epoll)

sequential

corosio (epoll)

15.84K ops/s

0.84%

+1.3%

sequential

asio (coroutines, epoll)

15.19K ops/s

1.00%

-2.9%

sequential

asio (callbacks, epoll)

15.65K ops/s

0.60%

baseline (epoll)

sequential_lockless

corosio (epoll)

15.96K ops/s

0.80%

+1.2%

sequential_lockless

asio (coroutines, epoll)

15.37K ops/s

0.95%

-2.6%

sequential_lockless

asio (callbacks, epoll)

15.78K ops/s

0.85%

baseline (epoll)


fan_out

Fan-out/fan-in coroutine coordination: a parent starts concurrent sub-requests against echo servers and awaits their completion via a shared latch.

io_uring

fan_out (io_uring) — Linux, part 1 ↑ faster · dotted line = asio (callbacks) · backend = io_uring corosio asio (coroutines) -6% -4% -2% +2% +4% 0% concurrent_parents/1 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents. +1% concurrent_parents/1 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents. -3% concurrent_parents/1 concurrent_parents/16 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents. +1% concurrent_parents/16 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents. -1% concurrent_parents/16 concurrent_parents/4 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents. +1% concurrent_parents/4 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents. -2% concurrent_parents/4 concurrent_parents_lockless/1 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents. +1% concurrent_parents_lockless/1 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents. -2% concurrent_parents_lockless/1 concurrent_parents_lockless/16 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents. -1% concurrent_parents_lockless/16 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents. -4% concurrent_parents_lockless/16 concurrent_parents_lockless/4 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents. +0% concurrent_parents_lockless/4 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents. -2% concurrent_parents_lockless/4
Detailed results
Benchmark Implementation Median CV vs asio

concurrent_parents/1

corosio (io_uring)

3.99K ops/s

0.32%

+1.3%

concurrent_parents/1

asio (coroutines, io_uring)

3.82K ops/s

1.11%

-3.1%

concurrent_parents/1

asio (callbacks, io_uring)

3.94K ops/s

0.93%

baseline (io_uring)

concurrent_parents/16

corosio (io_uring)

3.88K ops/s

0.18%

+1.1%

concurrent_parents/16

asio (coroutines, io_uring)

3.81K ops/s

1.01%

-0.7%

concurrent_parents/16

asio (callbacks, io_uring)

3.84K ops/s

1.14%

baseline (io_uring)

concurrent_parents/4

corosio (io_uring)

3.91K ops/s

0.17%

+1.2%

concurrent_parents/4

asio (coroutines, io_uring)

3.79K ops/s

0.91%

-1.8%

concurrent_parents/4

asio (callbacks, io_uring)

3.86K ops/s

0.98%

baseline (io_uring)

concurrent_parents_lockless/1

corosio (io_uring)

4.04K ops/s

0.32%

+1.2%

concurrent_parents_lockless/1

asio (coroutines, io_uring)

3.92K ops/s

1.38%

-1.9%

concurrent_parents_lockless/1

asio (callbacks, io_uring)

3.99K ops/s

1.30%

baseline (io_uring)

concurrent_parents_lockless/16

corosio (io_uring)

3.92K ops/s

0.26%

-0.9%

concurrent_parents_lockless/16

asio (coroutines, io_uring)

3.78K ops/s

1.27%

-4.4%

concurrent_parents_lockless/16

asio (callbacks, io_uring)

3.95K ops/s

1.16%

baseline (io_uring)

concurrent_parents_lockless/4

corosio (io_uring)

3.94K ops/s

0.25%

+0.2%

concurrent_parents_lockless/4

asio (coroutines, io_uring)

3.86K ops/s

1.14%

-1.9%

concurrent_parents_lockless/4

asio (callbacks, io_uring)

3.93K ops/s

1.12%

baseline (io_uring)

fan_out (io_uring) — Linux, part 2 ↑ faster · dotted line = asio (callbacks) · backend = io_uring corosio asio (coroutines) -15% -10% -5% +5% 0% fork_join/1 — One parent starts N sub-requests to echo servers and waits for all to finish before repeating; N is the fan-out width. fork_join/1 — One parent starts N sub-requests to echo servers and waits for all to finish before repeating; N is the fan-out width. -11% fork_join/1 fork_join/16 — One parent starts N sub-requests to echo servers and waits for all to finish before repeating; N is the fan-out width. fork_join/16 — One parent starts N sub-requests to echo servers and waits for all to finish before repeating; N is the fan-out width. fork_join/16 fork_join/4 — One parent starts N sub-requests to echo servers and waits for all to finish before repeating; N is the fan-out width. -2% fork_join/4 — One parent starts N sub-requests to echo servers and waits for all to finish before repeating; N is the fan-out width. fork_join/4 fork_join/64 — One parent starts N sub-requests to echo servers and waits for all to finish before repeating; N is the fan-out width. +2% fork_join/64 — One parent starts N sub-requests to echo servers and waits for all to finish before repeating; N is the fan-out width. fork_join/64 fork_join_lockless/1 — Same as fork_join, with the context in single-threaded lockless mode; N is the fan-out width. fork_join_lockless/1 — Same as fork_join, with the context in single-threaded lockless mode; N is the fan-out width. fork_join_lockless/1 fork_join_lockless/16 — Same as fork_join, with the context in single-threaded lockless mode; N is the fan-out width. fork_join_lockless/16 — Same as fork_join, with the context in single-threaded lockless mode; N is the fan-out width. fork_join_lockless/16 fork_join_lockless/4 — Same as fork_join, with the context in single-threaded lockless mode; N is the fan-out width. fork_join_lockless/4 — Same as fork_join, with the context in single-threaded lockless mode; N is the fan-out width. fork_join_lockless/4 fork_join_lockless/64 — Same as fork_join, with the context in single-threaded lockless mode; N is the fan-out width. fork_join_lockless/64 — Same as fork_join, with the context in single-threaded lockless mode; N is the fan-out width. -1% fork_join_lockless/64 nested/16 — Two-level fan-out: the parent starts N groups of 4 sub-requests each, each group awaited via its own latch; N is the number of groups. nested/16 — Two-level fan-out: the parent starts N groups of 4 sub-requests each, each group awaited via its own latch; N is the number of groups. nested/16 nested/4 — Two-level fan-out: the parent starts N groups of 4 sub-requests each, each group awaited via its own latch; N is the number of groups. nested/4 — Two-level fan-out: the parent starts N groups of 4 sub-requests each, each group awaited via its own latch; N is the number of groups. nested/4 nested_lockless/16 — Same as nested, with the context in single-threaded lockless mode; N is the number of groups. nested_lockless/16 — Same as nested, with the context in single-threaded lockless mode; N is the number of groups. nested_lockless/16 nested_lockless/4 — Same as nested, with the context in single-threaded lockless mode; N is the number of groups. nested_lockless/4 — Same as nested, with the context in single-threaded lockless mode; N is the number of groups. nested_lockless/4
Detailed results
Benchmark Implementation Median CV vs asio

fork_join/1

corosio (io_uring)

54.58K ops/s

0.25%

+0.6%

fork_join/1

asio (coroutines, io_uring)

48.29K ops/s

1.17%

-11.0%

fork_join/1

asio (callbacks, io_uring)

54.25K ops/s

1.13%

baseline (io_uring)

fork_join/16

corosio (io_uring)

3.99K ops/s

1.03%

+1.2%

fork_join/16

asio (coroutines, io_uring)

3.82K ops/s

1.05%

-3.2%

fork_join/16

asio (callbacks, io_uring)

3.94K ops/s

0.79%

baseline (io_uring)

fork_join/4

corosio (io_uring)

15.01K ops/s

0.45%

-1.8%

fork_join/4

asio (coroutines, io_uring)

14.51K ops/s

1.15%

-5.1%

fork_join/4

asio (callbacks, io_uring)

15.28K ops/s

0.73%

baseline (io_uring)

fork_join/64

corosio (io_uring)

978.5 ops/s

0.80%

+1.8%

fork_join/64

asio (coroutines, io_uring)

954.1 ops/s

0.89%

-0.8%

fork_join/64

asio (callbacks, io_uring)

961.5 ops/s

0.82%

baseline (io_uring)

fork_join_lockless/1

corosio (io_uring)

56.19K ops/s

0.86%

+1.7%

fork_join_lockless/1

asio (coroutines, io_uring)

49.90K ops/s

1.21%

-9.7%

fork_join_lockless/1

asio (callbacks, io_uring)

55.25K ops/s

1.10%

baseline (io_uring)

fork_join_lockless/16

corosio (io_uring)

4.04K ops/s

1.02%

+1.4%

fork_join_lockless/16

asio (coroutines, io_uring)

3.92K ops/s

0.84%

-1.6%

fork_join_lockless/16

asio (callbacks, io_uring)

3.99K ops/s

1.02%

baseline (io_uring)

fork_join_lockless/4

corosio (io_uring)

15.30K ops/s

1.16%

-1.1%

fork_join_lockless/4

asio (coroutines, io_uring)

15.00K ops/s

1.22%

-3.0%

fork_join_lockless/4

asio (callbacks, io_uring)

15.46K ops/s

1.13%

baseline (io_uring)

fork_join_lockless/64

corosio (io_uring)

985.0 ops/s

0.87%

+1.2%

fork_join_lockless/64

asio (coroutines, io_uring)

967.6 ops/s

1.07%

-0.6%

fork_join_lockless/64

asio (callbacks, io_uring)

973.5 ops/s

1.17%

baseline (io_uring)

nested/16

corosio (io_uring)

969.9 ops/s

0.81%

+0.9%

nested/16

asio (coroutines, io_uring)

933.1 ops/s

0.90%

-2.9%

nested/16

asio (callbacks, io_uring)

960.9 ops/s

1.05%

baseline (io_uring)

nested/4

corosio (io_uring)

3.96K ops/s

0.87%

+0.7%

nested/4

asio (coroutines, io_uring)

3.79K ops/s

1.12%

-3.7%

nested/4

asio (callbacks, io_uring)

3.93K ops/s

1.12%

baseline (io_uring)

nested_lockless/16

corosio (io_uring)

979.9 ops/s

0.27%

+0.6%

nested_lockless/16

asio (coroutines, io_uring)

941.4 ops/s

0.91%

-3.3%

nested_lockless/16

asio (callbacks, io_uring)

973.9 ops/s

0.99%

baseline (io_uring)

nested_lockless/4

corosio (io_uring)

4.00K ops/s

0.31%

+0.3%

nested_lockless/4

asio (coroutines, io_uring)

3.81K ops/s

1.09%

-4.7%

nested_lockless/4

asio (callbacks, io_uring)

3.99K ops/s

1.12%

baseline (io_uring)

epoll

fan_out (epoll) — Linux, part 1 ↑ faster · dotted line = asio (callbacks) · backend = epoll corosio asio (coroutines) -10% -7.5% -5% -2.5% +2.5% 0% concurrent_parents/1 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents. -6% concurrent_parents/1 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents. -5% concurrent_parents/1 concurrent_parents/16 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents. -7% concurrent_parents/16 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents. -4% concurrent_parents/16 concurrent_parents/4 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents. -7% concurrent_parents/4 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents. -4% concurrent_parents/4 concurrent_parents_lockless/1 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents. -6% concurrent_parents_lockless/1 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents. -5% concurrent_parents_lockless/1 concurrent_parents_lockless/16 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents. -7% concurrent_parents_lockless/16 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents. -4% concurrent_parents_lockless/16 concurrent_parents_lockless/4 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents. -6% concurrent_parents_lockless/4 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents. -5% concurrent_parents_lockless/4
Detailed results
Benchmark Implementation Median CV vs asio

concurrent_parents/1

corosio (epoll)

3.83K ops/s

0.85%

-6.1%

concurrent_parents/1

asio (coroutines, epoll)

3.88K ops/s

0.98%

-5.0%

concurrent_parents/1

asio (callbacks, epoll)

4.08K ops/s

1.11%

baseline (epoll)

concurrent_parents/16

corosio (epoll)

3.71K ops/s

1.02%

-6.8%

concurrent_parents/16

asio (coroutines, epoll)

3.81K ops/s

1.07%

-4.1%

concurrent_parents/16

asio (callbacks, epoll)

3.98K ops/s

0.90%

baseline (epoll)

concurrent_parents/4

corosio (epoll)

3.72K ops/s

0.80%

-6.8%

concurrent_parents/4

asio (coroutines, epoll)

3.81K ops/s

1.05%

-4.4%

concurrent_parents/4

asio (callbacks, epoll)

3.99K ops/s

1.02%

baseline (epoll)

concurrent_parents_lockless/1

corosio (epoll)

3.87K ops/s

1.00%

-5.9%

concurrent_parents_lockless/1

asio (coroutines, epoll)

3.91K ops/s

0.97%

-5.0%

concurrent_parents_lockless/1

asio (callbacks, epoll)

4.12K ops/s

0.33%

baseline (epoll)

concurrent_parents_lockless/16

corosio (epoll)

3.75K ops/s

1.12%

-6.7%

concurrent_parents_lockless/16

asio (coroutines, epoll)

3.84K ops/s

0.96%

-4.4%

concurrent_parents_lockless/16

asio (callbacks, epoll)

4.02K ops/s

0.36%

baseline (epoll)

concurrent_parents_lockless/4

corosio (epoll)

3.76K ops/s

1.15%

-6.5%

concurrent_parents_lockless/4

asio (coroutines, epoll)

3.83K ops/s

0.98%

-4.7%

concurrent_parents_lockless/4

asio (callbacks, epoll)

4.02K ops/s

0.37%

baseline (epoll)

fan_out (epoll) — Linux, part 2 ↑ faster · dotted line = asio (callbacks) · backend = epoll corosio asio (coroutines) -15% -10% -5% +5% 0% fork_join/1 — One parent starts N sub-requests to echo servers and waits for all to finish before repeating; N is the fan-out width. -8% fork_join/1 — One parent starts N sub-requests to echo servers and waits for all to finish before repeating; N is the fan-out width. -12% fork_join/1 fork_join/16 — One parent starts N sub-requests to echo servers and waits for all to finish before repeating; N is the fan-out width. fork_join/16 — One parent starts N sub-requests to echo servers and waits for all to finish before repeating; N is the fan-out width. fork_join/16 fork_join/4 — One parent starts N sub-requests to echo servers and waits for all to finish before repeating; N is the fan-out width. fork_join/4 — One parent starts N sub-requests to echo servers and waits for all to finish before repeating; N is the fan-out width. fork_join/4 fork_join/64 — One parent starts N sub-requests to echo servers and waits for all to finish before repeating; N is the fan-out width. fork_join/64 — One parent starts N sub-requests to echo servers and waits for all to finish before repeating; N is the fan-out width. -4% fork_join/64 fork_join_lockless/1 — Same as fork_join, with the context in single-threaded lockless mode; N is the fan-out width. fork_join_lockless/1 — Same as fork_join, with the context in single-threaded lockless mode; N is the fan-out width. fork_join_lockless/1 fork_join_lockless/16 — Same as fork_join, with the context in single-threaded lockless mode; N is the fan-out width. fork_join_lockless/16 — Same as fork_join, with the context in single-threaded lockless mode; N is the fan-out width. fork_join_lockless/16 fork_join_lockless/4 — Same as fork_join, with the context in single-threaded lockless mode; N is the fan-out width. -6% fork_join_lockless/4 — Same as fork_join, with the context in single-threaded lockless mode; N is the fan-out width. fork_join_lockless/4 fork_join_lockless/64 — Same as fork_join, with the context in single-threaded lockless mode; N is the fan-out width. fork_join_lockless/64 — Same as fork_join, with the context in single-threaded lockless mode; N is the fan-out width. fork_join_lockless/64 nested/16 — Two-level fan-out: the parent starts N groups of 4 sub-requests each, each group awaited via its own latch; N is the number of groups. nested/16 — Two-level fan-out: the parent starts N groups of 4 sub-requests each, each group awaited via its own latch; N is the number of groups. nested/16 nested/4 — Two-level fan-out: the parent starts N groups of 4 sub-requests each, each group awaited via its own latch; N is the number of groups. nested/4 — Two-level fan-out: the parent starts N groups of 4 sub-requests each, each group awaited via its own latch; N is the number of groups. nested/4 nested_lockless/16 — Same as nested, with the context in single-threaded lockless mode; N is the number of groups. nested_lockless/16 — Same as nested, with the context in single-threaded lockless mode; N is the number of groups. nested_lockless/16 nested_lockless/4 — Same as nested, with the context in single-threaded lockless mode; N is the number of groups. nested_lockless/4 — Same as nested, with the context in single-threaded lockless mode; N is the number of groups. nested_lockless/4
Detailed results
Benchmark Implementation Median CV vs asio

fork_join/1

corosio (epoll)

56.08K ops/s

0.18%

-7.9%

fork_join/1

asio (coroutines, epoll)

53.31K ops/s

0.98%

-12.5%

fork_join/1

asio (callbacks, epoll)

60.90K ops/s

1.26%

baseline (epoll)

fork_join/16

corosio (epoll)

3.82K ops/s

0.19%

-6.1%

fork_join/16

asio (coroutines, epoll)

3.88K ops/s

1.12%

-4.6%

fork_join/16

asio (callbacks, epoll)

4.07K ops/s

1.16%

baseline (epoll)

fork_join/4

corosio (epoll)

15.14K ops/s

0.09%

-5.8%

fork_join/4

asio (coroutines, epoll)

15.00K ops/s

1.11%

-6.6%

fork_join/4

asio (callbacks, epoll)

16.07K ops/s

1.26%

baseline (epoll)

fork_join/64

corosio (epoll)

930.6 ops/s

0.43%

-6.1%

fork_join/64

asio (coroutines, epoll)

953.8 ops/s

1.23%

-3.8%

fork_join/64

asio (callbacks, epoll)

991.4 ops/s

0.87%

baseline (epoll)

fork_join_lockless/1

corosio (epoll)

57.18K ops/s

0.89%

-7.2%

fork_join_lockless/1

asio (coroutines, epoll)

54.01K ops/s

1.17%

-12.3%

fork_join_lockless/1

asio (callbacks, epoll)

61.59K ops/s

0.89%

baseline (epoll)

fork_join_lockless/16

corosio (epoll)

3.87K ops/s

1.24%

-5.7%

fork_join_lockless/16

asio (coroutines, epoll)

3.91K ops/s

1.05%

-4.8%

fork_join_lockless/16

asio (callbacks, epoll)

4.11K ops/s

0.22%

baseline (epoll)

fork_join_lockless/4

corosio (epoll)

15.34K ops/s

1.06%

-5.6%

fork_join_lockless/4

asio (coroutines, epoll)

15.19K ops/s

0.99%

-6.5%

fork_join_lockless/4

asio (callbacks, epoll)

16.25K ops/s

0.15%

baseline (epoll)

fork_join_lockless/64

corosio (epoll)

941.1 ops/s

1.17%

-5.9%

fork_join_lockless/64

asio (coroutines, epoll)

961.0 ops/s

0.99%

-3.9%

fork_join_lockless/64

asio (callbacks, epoll)

1.00K ops/s

0.20%

baseline (epoll)

nested/16

corosio (epoll)

922.3 ops/s

1.03%

-6.9%

nested/16

asio (coroutines, epoll)

942.5 ops/s

0.26%

-4.8%

nested/16

asio (callbacks, epoll)

990.1 ops/s

0.84%

baseline (epoll)

nested/4

corosio (epoll)

3.80K ops/s

1.08%

-6.7%

nested/4

asio (coroutines, epoll)

3.82K ops/s

0.34%

-6.0%

nested/4

asio (callbacks, epoll)

4.07K ops/s

0.59%

baseline (epoll)

nested_lockless/16

corosio (epoll)

931.8 ops/s

0.91%

-6.9%

nested_lockless/16

asio (coroutines, epoll)

951.6 ops/s

0.97%

-4.9%

nested_lockless/16

asio (callbacks, epoll)

1.00K ops/s

1.16%

baseline (epoll)

nested_lockless/4

corosio (epoll)

3.84K ops/s

0.87%

-6.5%

nested_lockless/4

asio (coroutines, epoll)

3.87K ops/s

1.01%

-5.8%

nested_lockless/4

asio (callbacks, epoll)

4.11K ops/s

1.10%

baseline (epoll)


http_server

Request/response throughput of a minimal HTTP/1.1 server exchanging a fixed small request and canned response over persistent TCP loopback connections.

io_uring

http_server (io_uring) — Linux ↑ faster · dotted line = asio (callbacks) · backend = io_uring corosio asio (coroutines) -100% +100% +200% 0% concurrent/1 — N client/server pairs run the single_conn request/response loop concurrently; N is the number of connections. 0% concurrent/1 — N client/server pairs run the single_conn request/response loop concurrently; N is the number of connections. concurrent/1 concurrent/16 — N client/server pairs run the single_conn request/response loop concurrently; N is the number of connections. concurrent/16 — N client/server pairs run the single_conn request/response loop concurrently; N is the number of connections. concurrent/16 concurrent/32 — N client/server pairs run the single_conn request/response loop concurrently; N is the number of connections. concurrent/32 — N client/server pairs run the single_conn request/response loop concurrently; N is the number of connections. concurrent/32 concurrent/4 — N client/server pairs run the single_conn request/response loop concurrently; N is the number of connections. concurrent/4 — N client/server pairs run the single_conn request/response loop concurrently; N is the number of connections. concurrent/4 multithread/1 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. multithread/1 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. multithread/1 multithread/16 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. multithread/16 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. -4% multithread/16 multithread/2 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. multithread/2 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. +8% multithread/2 multithread/4 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. +158% multithread/4 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. multithread/4 multithread/8 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. multithread/8 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. multithread/8 single_conn — One client repeatedly sends a fixed small HTTP request to one server and reads the response. single_conn — One client repeatedly sends a fixed small HTTP request to one server and reads the response. single_conn single_conn_lockless — Same as single_conn, with the context in single-threaded lockless mode. single_conn_lockless — Same as single_conn, with the context in single-threaded lockless mode. single_conn_lockless
Detailed results
Benchmark Implementation Median CV vs asio

concurrent/1

corosio (io_uring)

53.15K ops/s

1.13%

-0.2%

concurrent/1

asio (coroutines, io_uring)

52.39K ops/s

1.00%

-1.6%

concurrent/1

asio (callbacks, io_uring)

53.24K ops/s

1.23%

baseline (io_uring)

concurrent/16

corosio (io_uring)

63.19K ops/s

0.74%

+2.5%

concurrent/16

asio (coroutines, io_uring)

60.78K ops/s

0.94%

-1.4%

concurrent/16

asio (callbacks, io_uring)

61.66K ops/s

0.89%

baseline (io_uring)

concurrent/32

corosio (io_uring)

63.20K ops/s

0.14%

+2.7%

concurrent/32

asio (coroutines, io_uring)

60.59K ops/s

1.14%

-1.5%

concurrent/32

asio (callbacks, io_uring)

61.52K ops/s

1.04%

baseline (io_uring)

concurrent/4

corosio (io_uring)

61.10K ops/s

0.97%

+2.3%

concurrent/4

asio (coroutines, io_uring)

58.87K ops/s

0.80%

-1.4%

concurrent/4

asio (callbacks, io_uring)

59.71K ops/s

0.96%

baseline (io_uring)

multithread/1

corosio (io_uring)

63.06K ops/s

0.09%

+2.4%

multithread/1

asio (coroutines, io_uring)

60.63K ops/s

0.85%

-1.5%

multithread/1

asio (callbacks, io_uring)

61.58K ops/s

1.08%

baseline (io_uring)

multithread/16

corosio (io_uring)

100.8K ops/s

0.31%

+139.6%

multithread/16

asio (coroutines, io_uring)

40.30K ops/s

1.15%

-4.2%

multithread/16

asio (callbacks, io_uring)

42.06K ops/s

1.20%

baseline (io_uring)

multithread/2

corosio (io_uring)

74.85K ops/s

0.22%

+58.8%

multithread/2

asio (coroutines, io_uring)

50.90K ops/s

9.06%

+8.0%

multithread/2

asio (callbacks, io_uring)

47.13K ops/s

7.86%

baseline (io_uring)

multithread/4

corosio (io_uring)

119.9K ops/s

0.55%

+158.4%

multithread/4

asio (coroutines, io_uring)

45.95K ops/s

0.66%

-1.0%

multithread/4

asio (callbacks, io_uring)

46.42K ops/s

0.35%

baseline (io_uring)

multithread/8

corosio (io_uring)

112.1K ops/s

0.28%

+158.0%

multithread/8

asio (coroutines, io_uring)

42.16K ops/s

0.67%

-3.0%

multithread/8

asio (callbacks, io_uring)

43.47K ops/s

0.76%

baseline (io_uring)

single_conn

corosio (io_uring)

53.14K ops/s

1.18%

-0.1%

single_conn

asio (coroutines, io_uring)

52.40K ops/s

0.11%

-1.4%

single_conn

asio (callbacks, io_uring)

53.17K ops/s

1.37%

baseline (io_uring)

single_conn_lockless

corosio (io_uring)

54.98K ops/s

1.12%

+2.3%

single_conn_lockless

asio (coroutines, io_uring)

53.00K ops/s

0.39%

-1.4%

single_conn_lockless

asio (callbacks, io_uring)

53.76K ops/s

1.35%

baseline (io_uring)

epoll

http_server (epoll) — Linux ↑ faster · dotted line = asio (callbacks) · backend = epoll corosio asio (coroutines) -7.5% -5% -2.5% +2.5% 0% concurrent/1 — N client/server pairs run the single_conn request/response loop concurrently; N is the number of connections. concurrent/1 — N client/server pairs run the single_conn request/response loop concurrently; N is the number of connections. -2% concurrent/1 concurrent/16 — N client/server pairs run the single_conn request/response loop concurrently; N is the number of connections. concurrent/16 — N client/server pairs run the single_conn request/response loop concurrently; N is the number of connections. concurrent/16 concurrent/32 — N client/server pairs run the single_conn request/response loop concurrently; N is the number of connections. concurrent/32 — N client/server pairs run the single_conn request/response loop concurrently; N is the number of connections. concurrent/32 concurrent/4 — N client/server pairs run the single_conn request/response loop concurrently; N is the number of connections. concurrent/4 — N client/server pairs run the single_conn request/response loop concurrently; N is the number of connections. concurrent/4 multithread/1 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. multithread/1 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. multithread/1 multithread/16 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. +0% multithread/16 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. -4% multithread/16 multithread/2 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. -6% multithread/2 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. multithread/2 multithread/4 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. multithread/4 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. multithread/4 multithread/8 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. multithread/8 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count. multithread/8 single_conn — One client repeatedly sends a fixed small HTTP request to one server and reads the response. single_conn — One client repeatedly sends a fixed small HTTP request to one server and reads the response. single_conn single_conn_lockless — Same as single_conn, with the context in single-threaded lockless mode. single_conn_lockless — Same as single_conn, with the context in single-threaded lockless mode. single_conn_lockless
Detailed results
Benchmark Implementation Median CV vs asio

concurrent/1

corosio (epoll)

56.79K ops/s

0.95%

-4.1%

concurrent/1

asio (coroutines, epoll)

57.92K ops/s

0.91%

-2.2%

concurrent/1

asio (callbacks, epoll)

59.22K ops/s

0.91%

baseline (epoll)

concurrent/16

corosio (epoll)

59.88K ops/s

0.93%

-4.6%

concurrent/16

asio (coroutines, epoll)

60.97K ops/s

0.18%

-2.9%

concurrent/16

asio (callbacks, epoll)

62.77K ops/s

0.76%

baseline (epoll)

concurrent/32

corosio (epoll)

59.45K ops/s

1.14%

-4.6%

concurrent/32

asio (coroutines, epoll)

60.45K ops/s

0.20%

-3.0%

concurrent/32

asio (callbacks, epoll)

62.34K ops/s

0.69%

baseline (epoll)

concurrent/4

corosio (epoll)

59.24K ops/s

0.86%

-4.6%

concurrent/4

asio (coroutines, epoll)

60.41K ops/s

0.19%

-2.7%

concurrent/4

asio (callbacks, epoll)

62.12K ops/s

0.41%

baseline (epoll)

multithread/1

corosio (epoll)

59.36K ops/s

1.23%

-4.7%

multithread/1

asio (coroutines, epoll)

60.52K ops/s

0.17%

-2.8%

multithread/1

asio (callbacks, epoll)

62.27K ops/s

0.83%

baseline (epoll)

multithread/16

corosio (epoll)

164.1K ops/s

0.40%

+0.3%

multithread/16

asio (coroutines, epoll)

156.9K ops/s

0.51%

-4.1%

multithread/16

asio (callbacks, epoll)

163.6K ops/s

0.43%

baseline (epoll)

multithread/2

corosio (epoll)

88.17K ops/s

0.48%

-5.7%

multithread/2

asio (coroutines, epoll)

90.00K ops/s

0.30%

-3.7%

multithread/2

asio (callbacks, epoll)

93.49K ops/s

0.62%

baseline (epoll)

multithread/4

corosio (epoll)

161.3K ops/s

0.82%

-3.3%

multithread/4

asio (coroutines, epoll)

160.2K ops/s

0.55%

-4.0%

multithread/4

asio (callbacks, epoll)

166.8K ops/s

0.61%

baseline (epoll)

multithread/8

corosio (epoll)

163.4K ops/s

0.43%

-1.0%

multithread/8

asio (coroutines, epoll)

158.5K ops/s

0.56%

-4.0%

multithread/8

asio (callbacks, epoll)

165.0K ops/s

0.68%

baseline (epoll)

single_conn

corosio (epoll)

56.69K ops/s

1.10%

-4.1%

single_conn

asio (coroutines, epoll)

57.80K ops/s

0.99%

-2.2%

single_conn

asio (callbacks, epoll)

59.12K ops/s

1.01%

baseline (epoll)

single_conn_lockless

corosio (epoll)

57.38K ops/s

0.88%

-4.0%

single_conn_lockless

asio (coroutines, epoll)

58.39K ops/s

0.82%

-2.3%

single_conn_lockless

asio (callbacks, epoll)

59.78K ops/s

1.11%

baseline (epoll)


local_socket_latency

Round-trip latency of a single Unix domain stream socket write/read exchange across message sizes and concurrent pair counts.

io_uring

local_socket_latency (io_uring) — Linux ↑ faster (lower mean latency) · dotted line = asio (callbacks) · backend = io_uring corosio asio (coroutines) -20% +20% +40% 0% concurrent/1 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/1 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. -3% concurrent/1 concurrent/16 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/16 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/16 concurrent/4 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/4 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/4 concurrent_lockless/1 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. concurrent_lockless/1 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. concurrent_lockless/1 concurrent_lockless/16 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. +3% concurrent_lockless/16 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. concurrent_lockless/16 concurrent_lockless/4 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. concurrent_lockless/4 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. concurrent_lockless/4 pingpong/1 — One connected Unix domain socket pair ping-pongs a message client->server->client; N is the message size in bytes. +34% pingpong/1 — One connected Unix domain socket pair ping-pongs a message client->server->client; N is the message size in bytes. pingpong/1 pingpong/1024 — One connected Unix domain socket pair ping-pongs a message client->server->client; N is the message size in bytes. pingpong/1024 — One connected Unix domain socket pair ping-pongs a message client->server->client; N is the message size in bytes. pingpong/1024 pingpong/64 — One connected Unix domain socket pair ping-pongs a message client->server->client; N is the message size in bytes. pingpong/64 — One connected Unix domain socket pair ping-pongs a message client->server->client; N is the message size in bytes. pingpong/64 pingpong_lockless/1 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/1 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/1 pingpong_lockless/1024 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/1024 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. -6% pingpong_lockless/1024 pingpong_lockless/64 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/64 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/64
Detailed results
Benchmark Implementation Median CV vs asio

concurrent/1

corosio (io_uring)

5.70 µs

5.75%

+33.3%

concurrent/1

asio (coroutines, io_uring)

8.79 µs

3.97%

-2.8%

concurrent/1

asio (callbacks, io_uring)

8.55 µs

3.35%

baseline (io_uring)

concurrent/16

corosio (io_uring)

93.17 µs

0.27%

+6.1%

concurrent/16

asio (coroutines, io_uring)

103.25 µs

1.02%

-4.0%

concurrent/16

asio (callbacks, io_uring)

99.25 µs

1.06%

baseline (io_uring)

concurrent/4

corosio (io_uring)

23.32 µs

1.59%

+11.8%

concurrent/4

asio (coroutines, io_uring)

27.97 µs

1.04%

-5.9%

concurrent/4

asio (callbacks, io_uring)

26.43 µs

1.49%

baseline (io_uring)

concurrent_lockless/1

corosio (io_uring)

5.63 µs

0.68%

+31.3%

concurrent_lockless/1

asio (coroutines, io_uring)

8.46 µs

3.47%

-3.3%

concurrent_lockless/1

asio (callbacks, io_uring)

8.19 µs

3.72%

baseline (io_uring)

concurrent_lockless/16

corosio (io_uring)

92.85 µs

0.61%

+2.9%

concurrent_lockless/16

asio (coroutines, io_uring)

99.69 µs

0.98%

-4.3%

concurrent_lockless/16

asio (callbacks, io_uring)

95.58 µs

0.69%

baseline (io_uring)

concurrent_lockless/4

corosio (io_uring)

23.31 µs

1.33%

+8.9%

concurrent_lockless/4

asio (coroutines, io_uring)

26.87 µs

1.74%

-5.1%

concurrent_lockless/4

asio (callbacks, io_uring)

25.57 µs

1.72%

baseline (io_uring)

pingpong/1

corosio (io_uring)

5.63 µs

0.65%

+33.7%

pingpong/1

asio (coroutines, io_uring)

8.77 µs

3.97%

-3.3%

pingpong/1

asio (callbacks, io_uring)

8.49 µs

3.09%

baseline (io_uring)

pingpong/1024

corosio (io_uring)

6.54 µs

5.86%

+25.7%

pingpong/1024

asio (coroutines, io_uring)

9.08 µs

3.59%

-3.1%

pingpong/1024

asio (callbacks, io_uring)

8.81 µs

3.15%

baseline (io_uring)

pingpong/64

corosio (io_uring)

5.66 µs

5.63%

+33.7%

pingpong/64

asio (coroutines, io_uring)

8.79 µs

2.28%

-2.9%

pingpong/64

asio (callbacks, io_uring)

8.54 µs

4.28%

baseline (io_uring)

pingpong_lockless/1

corosio (io_uring)

5.61 µs

4.58%

+31.1%

pingpong_lockless/1

asio (coroutines, io_uring)

8.45 µs

3.98%

-3.8%

pingpong_lockless/1

asio (callbacks, io_uring)

8.14 µs

2.78%

baseline (io_uring)

pingpong_lockless/1024

corosio (io_uring)

6.51 µs

5.60%

+25.8%

pingpong_lockless/1024

asio (coroutines, io_uring)

9.32 µs

3.63%

-6.2%

pingpong_lockless/1024

asio (callbacks, io_uring)

8.78 µs

3.76%

baseline (io_uring)

pingpong_lockless/64

corosio (io_uring)

5.65 µs

4.16%

+31.1%

pingpong_lockless/64

asio (coroutines, io_uring)

8.44 µs

0.70%

-3.0%

pingpong_lockless/64

asio (callbacks, io_uring)

8.19 µs

4.39%

baseline (io_uring)

epoll

local_socket_latency (epoll) — Linux ↑ faster (lower mean latency) · dotted line = asio (callbacks) · backend = epoll corosio asio (coroutines) -20% -10% +10% +20% +30% 0% concurrent/1 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/1 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/1 concurrent/16 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/16 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/16 concurrent/4 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/4 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/4 concurrent_lockless/1 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. concurrent_lockless/1 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. concurrent_lockless/1 concurrent_lockless/16 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. -10% concurrent_lockless/16 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. concurrent_lockless/16 concurrent_lockless/4 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. concurrent_lockless/4 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. concurrent_lockless/4 pingpong/1 — One connected Unix domain socket pair ping-pongs a message client->server->client; N is the message size in bytes. pingpong/1 — One connected Unix domain socket pair ping-pongs a message client->server->client; N is the message size in bytes. pingpong/1 pingpong/1024 — One connected Unix domain socket pair ping-pongs a message client->server->client; N is the message size in bytes. +17% pingpong/1024 — One connected Unix domain socket pair ping-pongs a message client->server->client; N is the message size in bytes. +3% pingpong/1024 pingpong/64 — One connected Unix domain socket pair ping-pongs a message client->server->client; N is the message size in bytes. pingpong/64 — One connected Unix domain socket pair ping-pongs a message client->server->client; N is the message size in bytes. pingpong/64 pingpong_lockless/1 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/1 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. -8% pingpong_lockless/1 pingpong_lockless/1024 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/1024 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/1024 pingpong_lockless/64 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/64 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/64
Detailed results
Benchmark Implementation Median CV vs asio

concurrent/1

corosio (epoll)

7.11 µs

3.16%

+11.1%

concurrent/1

asio (coroutines, epoll)

8.35 µs

1.84%

-4.3%

concurrent/1

asio (callbacks, epoll)

8.00 µs

3.47%

baseline (epoll)

concurrent/16

corosio (epoll)

110.02 µs

0.62%

-8.1%

concurrent/16

asio (coroutines, epoll)

107.52 µs

0.33%

-5.6%

concurrent/16

asio (callbacks, epoll)

101.79 µs

0.46%

baseline (epoll)

concurrent/4

corosio (epoll)

27.76 µs

0.98%

-5.7%

concurrent/4

asio (coroutines, epoll)

28.35 µs

0.30%

-7.9%

concurrent/4

asio (callbacks, epoll)

26.26 µs

1.93%

baseline (epoll)

concurrent_lockless/1

corosio (epoll)

7.02 µs

0.71%

+10.1%

concurrent_lockless/1

asio (coroutines, epoll)

8.12 µs

3.21%

-3.9%

concurrent_lockless/1

asio (callbacks, epoll)

7.81 µs

0.61%

baseline (epoll)

concurrent_lockless/16

corosio (epoll)

109.06 µs

0.57%

-9.9%

concurrent_lockless/16

asio (coroutines, epoll)

104.31 µs

0.40%

-5.1%

concurrent_lockless/16

asio (callbacks, epoll)

99.23 µs

0.61%

baseline (epoll)

concurrent_lockless/4

corosio (epoll)

27.57 µs

1.25%

-5.3%

concurrent_lockless/4

asio (coroutines, epoll)

27.71 µs

1.01%

-5.8%

concurrent_lockless/4

asio (callbacks, epoll)

26.18 µs

1.59%

baseline (epoll)

pingpong/1

corosio (epoll)

7.09 µs

4.50%

+11.0%

pingpong/1

asio (coroutines, epoll)

8.31 µs

0.28%

-4.3%

pingpong/1

asio (callbacks, epoll)

7.97 µs

3.16%

baseline (epoll)

pingpong/1024

corosio (epoll)

7.38 µs

4.64%

+17.0%

pingpong/1024

asio (coroutines, epoll)

8.59 µs

4.33%

+3.3%

pingpong/1024

asio (callbacks, epoll)

8.89 µs

3.38%

baseline (epoll)

pingpong/64

corosio (epoll)

7.12 µs

4.87%

+16.3%

pingpong/64

asio (coroutines, epoll)

8.37 µs

3.29%

+1.7%

pingpong/64

asio (callbacks, epoll)

8.51 µs

3.87%

baseline (epoll)

pingpong_lockless/1

corosio (epoll)

6.98 µs

4.85%

+10.2%

pingpong_lockless/1

asio (coroutines, epoll)

8.44 µs

3.90%

-8.5%

pingpong_lockless/1

asio (callbacks, epoll)

7.78 µs

2.88%

baseline (epoll)

pingpong_lockless/1024

corosio (epoll)

7.49 µs

4.55%

+12.8%

pingpong_lockless/1024

asio (coroutines, epoll)

8.92 µs

3.41%

-3.8%

pingpong_lockless/1024

asio (callbacks, epoll)

8.60 µs

2.94%

baseline (epoll)

pingpong_lockless/64

corosio (epoll)

7.01 µs

4.13%

+10.3%

pingpong_lockless/64

asio (coroutines, epoll)

8.12 µs

2.70%

-3.9%

pingpong_lockless/64

asio (callbacks, epoll)

7.82 µs

3.28%

baseline (epoll)


local_socket_throughput

Sustained byte throughput of a Unix domain stream socket pair under continuous streaming across chunk sizes and directions.

io_uring

local_socket_throughput (io_uring) — Linux, part 1 ↑ faster · dotted line = asio (callbacks) · backend = io_uring corosio asio (coroutines) -20% +20% +40% 0% bidirectional/1024 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. +27% bidirectional/1024 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. +5% bidirectional/1024 bidirectional/1048576 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. bidirectional/1048576 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. bidirectional/1048576 bidirectional/16384 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. bidirectional/16384 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. bidirectional/16384 bidirectional/262144 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. bidirectional/262144 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. -5% bidirectional/262144 bidirectional/4096 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. bidirectional/4096 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. bidirectional/4096 bidirectional/65536 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. -7% bidirectional/65536 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. bidirectional/65536 bidirectional_lockless/1024 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/1024 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/1024 bidirectional_lockless/1048576 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/1048576 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/1048576 bidirectional_lockless/16384 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/16384 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/16384 bidirectional_lockless/262144 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/262144 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/262144 bidirectional_lockless/4096 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/4096 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/4096 bidirectional_lockless/65536 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/65536 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/65536
Detailed results
Benchmark Implementation Median CV vs asio

bidirectional/1024

corosio (io_uring)

352.1 MB/s

0.75%

+26.7%

bidirectional/1024

asio (coroutines, io_uring)

291.0 MB/s

4.09%

+4.7%

bidirectional/1024

asio (callbacks, io_uring)

277.9 MB/s

4.07%

baseline (io_uring)

bidirectional/1048576

corosio (io_uring)

3.49 GB/s

2.94%

-2.4%

bidirectional/1048576

asio (coroutines, io_uring)

3.53 GB/s

1.16%

-1.3%

bidirectional/1048576

asio (callbacks, io_uring)

3.57 GB/s

2.34%

baseline (io_uring)

bidirectional/16384

corosio (io_uring)

2.97 GB/s

1.31%

-1.7%

bidirectional/16384

asio (coroutines, io_uring)

2.92 GB/s

4.85%

-3.4%

bidirectional/16384

asio (callbacks, io_uring)

3.02 GB/s

2.19%

baseline (io_uring)

bidirectional/262144

corosio (io_uring)

3.53 GB/s

1.14%

-1.8%

bidirectional/262144

asio (coroutines, io_uring)

3.40 GB/s

2.90%

-5.4%

bidirectional/262144

asio (callbacks, io_uring)

3.60 GB/s

2.77%

baseline (io_uring)

bidirectional/4096

corosio (io_uring)

1.13 GB/s

1.08%

+19.7%

bidirectional/4096

asio (coroutines, io_uring)

919.2 MB/s

0.69%

-2.5%

bidirectional/4096

asio (callbacks, io_uring)

942.9 MB/s

1.41%

baseline (io_uring)

bidirectional/65536

corosio (io_uring)

3.47 GB/s

1.55%

-7.2%

bidirectional/65536

asio (coroutines, io_uring)

3.59 GB/s

3.99%

-4.0%

bidirectional/65536

asio (callbacks, io_uring)

3.74 GB/s

1.60%

baseline (io_uring)

bidirectional_lockless/1024

corosio (io_uring)

357.0 MB/s

0.59%

+26.3%

bidirectional_lockless/1024

asio (coroutines, io_uring)

278.9 MB/s

4.88%

-1.3%

bidirectional_lockless/1024

asio (callbacks, io_uring)

282.6 MB/s

5.69%

baseline (io_uring)

bidirectional_lockless/1048576

corosio (io_uring)

3.51 GB/s

2.14%

-3.4%

bidirectional_lockless/1048576

asio (coroutines, io_uring)

3.54 GB/s

2.14%

-2.7%

bidirectional_lockless/1048576

asio (callbacks, io_uring)

3.64 GB/s

2.82%

baseline (io_uring)

bidirectional_lockless/16384

corosio (io_uring)

3.01 GB/s

1.84%

-2.4%

bidirectional_lockless/16384

asio (coroutines, io_uring)

2.99 GB/s

1.83%

-3.1%

bidirectional_lockless/16384

asio (callbacks, io_uring)

3.08 GB/s

1.40%

baseline (io_uring)

bidirectional_lockless/262144

corosio (io_uring)

3.57 GB/s

1.64%

-2.0%

bidirectional_lockless/262144

asio (coroutines, io_uring)

3.45 GB/s

2.43%

-5.3%

bidirectional_lockless/262144

asio (callbacks, io_uring)

3.64 GB/s

3.19%

baseline (io_uring)

bidirectional_lockless/4096

corosio (io_uring)

1.14 GB/s

0.53%

+19.6%

bidirectional_lockless/4096

asio (coroutines, io_uring)

911.9 MB/s

3.21%

-4.1%

bidirectional_lockless/4096

asio (callbacks, io_uring)

951.1 MB/s

3.64%

baseline (io_uring)

bidirectional_lockless/65536

corosio (io_uring)

3.49 GB/s

1.55%

-7.0%

bidirectional_lockless/65536

asio (coroutines, io_uring)

3.65 GB/s

4.76%

-2.7%

bidirectional_lockless/65536

asio (callbacks, io_uring)

3.75 GB/s

3.01%

baseline (io_uring)

local_socket_throughput (io_uring) — Linux, part 2 ↑ faster · dotted line = asio (callbacks) · backend = io_uring corosio asio (coroutines) -40% -20% +20% +40% +60% 0% unidirectional/1024 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. +37% unidirectional/1024 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/1024 unidirectional/1048576 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/1048576 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/1048576 unidirectional/16384 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/16384 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/16384 unidirectional/262144 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/262144 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. -5% unidirectional/262144 unidirectional/4096 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/4096 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/4096 unidirectional/65536 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. -13% unidirectional/65536 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/65536 unidirectional_lockless/1024 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/1024 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. +4% unidirectional_lockless/1024 unidirectional_lockless/1048576 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/1048576 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/1048576 unidirectional_lockless/16384 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/16384 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/16384 unidirectional_lockless/262144 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/262144 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/262144 unidirectional_lockless/4096 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/4096 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/4096 unidirectional_lockless/65536 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/65536 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/65536
Detailed results
Benchmark Implementation Median CV vs asio

unidirectional/1024

corosio (io_uring)

352.5 MB/s

0.39%

+37.3%

unidirectional/1024

asio (coroutines, io_uring)

258.2 MB/s

4.13%

+0.6%

unidirectional/1024

asio (callbacks, io_uring)

256.7 MB/s

3.87%

baseline (io_uring)

unidirectional/1048576

corosio (io_uring)

3.49 GB/s

3.63%

-3.2%

unidirectional/1048576

asio (coroutines, io_uring)

3.51 GB/s

3.45%

-2.5%

unidirectional/1048576

asio (callbacks, io_uring)

3.60 GB/s

2.67%

baseline (io_uring)

unidirectional/16384

corosio (io_uring)

3.05 GB/s

1.31%

+6.4%

unidirectional/16384

asio (coroutines, io_uring)

2.79 GB/s

5.28%

-2.6%

unidirectional/16384

asio (callbacks, io_uring)

2.86 GB/s

2.00%

baseline (io_uring)

unidirectional/262144

corosio (io_uring)

3.54 GB/s

1.74%

-2.6%

unidirectional/262144

asio (coroutines, io_uring)

3.44 GB/s

3.24%

-5.4%

unidirectional/262144

asio (callbacks, io_uring)

3.63 GB/s

2.69%

baseline (io_uring)

unidirectional/4096

corosio (io_uring)

1.13 GB/s

0.93%

+27.6%

unidirectional/4096

asio (coroutines, io_uring)

863.4 MB/s

0.84%

-2.1%

unidirectional/4096

asio (callbacks, io_uring)

882.1 MB/s

4.00%

baseline (io_uring)

unidirectional/65536

corosio (io_uring)

3.52 GB/s

1.03%

-13.1%

unidirectional/65536

asio (coroutines, io_uring)

3.85 GB/s

3.58%

-4.9%

unidirectional/65536

asio (callbacks, io_uring)

4.05 GB/s

2.65%

baseline (io_uring)

unidirectional_lockless/1024

corosio (io_uring)

355.5 MB/s

0.91%

+34.5%

unidirectional_lockless/1024

asio (coroutines, io_uring)

274.2 MB/s

3.83%

+3.7%

unidirectional_lockless/1024

asio (callbacks, io_uring)

264.4 MB/s

4.69%

baseline (io_uring)

unidirectional_lockless/1048576

corosio (io_uring)

3.54 GB/s

3.16%

-1.1%

unidirectional_lockless/1048576

asio (coroutines, io_uring)

3.55 GB/s

3.51%

-0.9%

unidirectional_lockless/1048576

asio (callbacks, io_uring)

3.58 GB/s

3.50%

baseline (io_uring)

unidirectional_lockless/16384

corosio (io_uring)

3.04 GB/s

1.20%

+5.8%

unidirectional_lockless/16384

asio (coroutines, io_uring)

2.88 GB/s

7.29%

+0.1%

unidirectional_lockless/16384

asio (callbacks, io_uring)

2.87 GB/s

1.93%

baseline (io_uring)

unidirectional_lockless/262144

corosio (io_uring)

3.52 GB/s

2.27%

-2.5%

unidirectional_lockless/262144

asio (coroutines, io_uring)

3.46 GB/s

2.68%

-4.1%

unidirectional_lockless/262144

asio (callbacks, io_uring)

3.61 GB/s

3.49%

baseline (io_uring)

unidirectional_lockless/4096

corosio (io_uring)

1.14 GB/s

0.50%

+25.3%

unidirectional_lockless/4096

asio (coroutines, io_uring)

879.8 MB/s

1.51%

-2.9%

unidirectional_lockless/4096

asio (callbacks, io_uring)

905.7 MB/s

0.80%

baseline (io_uring)

unidirectional_lockless/65536

corosio (io_uring)

3.56 GB/s

1.67%

-11.3%

unidirectional_lockless/65536

asio (coroutines, io_uring)

3.87 GB/s

2.93%

-3.7%

unidirectional_lockless/65536

asio (callbacks, io_uring)

4.01 GB/s

1.33%

baseline (io_uring)

epoll

local_socket_throughput (epoll) — Linux, part 1 ↑ faster · dotted line = asio (callbacks) · backend = epoll corosio asio (coroutines) -30% -20% -10% +10% +20% 0% bidirectional/1024 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. bidirectional/1024 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. -14% bidirectional/1024 bidirectional/1048576 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. bidirectional/1048576 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. bidirectional/1048576 bidirectional/16384 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. bidirectional/16384 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. bidirectional/16384 bidirectional/262144 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. bidirectional/262144 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. bidirectional/262144 bidirectional/4096 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. +11% bidirectional/4096 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. bidirectional/4096 bidirectional/65536 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. bidirectional/65536 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes. bidirectional/65536 bidirectional_lockless/1024 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/1024 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/1024 bidirectional_lockless/1048576 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/1048576 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/1048576 bidirectional_lockless/16384 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/16384 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/16384 bidirectional_lockless/262144 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/262144 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. +4% bidirectional_lockless/262144 bidirectional_lockless/4096 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/4096 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/4096 bidirectional_lockless/65536 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. -18% bidirectional_lockless/65536 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/65536
Detailed results
Benchmark Implementation Median CV vs asio

bidirectional/1024

corosio (epoll)

305.0 MB/s

0.82%

+0.2%

bidirectional/1024

asio (coroutines, epoll)

262.9 MB/s

4.80%

-13.7%

bidirectional/1024

asio (callbacks, epoll)

304.5 MB/s

4.57%

baseline (epoll)

bidirectional/1048576

corosio (epoll)

3.22 GB/s

1.56%

-0.5%

bidirectional/1048576

asio (coroutines, epoll)

3.28 GB/s

2.34%

+1.4%

bidirectional/1048576

asio (callbacks, epoll)

3.24 GB/s

2.14%

baseline (epoll)

bidirectional/16384

corosio (epoll)

3.04 GB/s

1.35%

+2.0%

bidirectional/16384

asio (coroutines, epoll)

2.87 GB/s

2.94%

-3.7%

bidirectional/16384

asio (callbacks, epoll)

2.98 GB/s

3.43%

baseline (epoll)

bidirectional/262144

corosio (epoll)

3.25 GB/s

2.06%

+1.5%

bidirectional/262144

asio (coroutines, epoll)

3.31 GB/s

1.01%

+3.3%

bidirectional/262144

asio (callbacks, epoll)

3.21 GB/s

2.50%

baseline (epoll)

bidirectional/4096

corosio (epoll)

999.6 MB/s

0.84%

+10.7%

bidirectional/4096

asio (coroutines, epoll)

904.5 MB/s

2.66%

+0.2%

bidirectional/4096

asio (callbacks, epoll)

902.9 MB/s

4.13%

baseline (epoll)

bidirectional/65536

corosio (epoll)

3.03 GB/s

0.63%

-17.7%

bidirectional/65536

asio (coroutines, epoll)

3.51 GB/s

3.62%

-4.8%

bidirectional/65536

asio (callbacks, epoll)

3.68 GB/s

2.76%

baseline (epoll)

bidirectional_lockless/1024

corosio (epoll)

307.6 MB/s

1.64%

+8.7%

bidirectional_lockless/1024

asio (coroutines, epoll)

271.3 MB/s

3.50%

-4.1%

bidirectional_lockless/1024

asio (callbacks, epoll)

282.9 MB/s

4.86%

baseline (epoll)

bidirectional_lockless/1048576

corosio (epoll)

3.22 GB/s

2.08%

-0.9%

bidirectional_lockless/1048576

asio (coroutines, epoll)

3.28 GB/s

1.88%

+0.9%

bidirectional_lockless/1048576

asio (callbacks, epoll)

3.25 GB/s

2.55%

baseline (epoll)

bidirectional_lockless/16384

corosio (epoll)

3.08 GB/s

2.21%

+0.5%

bidirectional_lockless/16384

asio (coroutines, epoll)

2.95 GB/s

1.69%

-3.8%

bidirectional_lockless/16384

asio (callbacks, epoll)

3.07 GB/s

2.55%

baseline (epoll)

bidirectional_lockless/262144

corosio (epoll)

3.27 GB/s

2.61%

+1.9%

bidirectional_lockless/262144

asio (coroutines, epoll)

3.34 GB/s

1.09%

+3.9%

bidirectional_lockless/262144

asio (callbacks, epoll)

3.21 GB/s

2.69%

baseline (epoll)

bidirectional_lockless/4096

corosio (epoll)

1.01 GB/s

0.93%

+4.4%

bidirectional_lockless/4096

asio (coroutines, epoll)

914.9 MB/s

1.57%

-5.1%

bidirectional_lockless/4096

asio (callbacks, epoll)

964.0 MB/s

3.48%

baseline (epoll)

bidirectional_lockless/65536

corosio (epoll)

3.03 GB/s

0.65%

-18.0%

bidirectional_lockless/65536

asio (coroutines, epoll)

3.55 GB/s

4.37%

-3.8%

bidirectional_lockless/65536

asio (callbacks, epoll)

3.69 GB/s

5.00%

baseline (epoll)

local_socket_throughput (epoll) — Linux, part 2 ↑ faster · dotted line = asio (callbacks) · backend = epoll corosio asio (coroutines) -40% -20% +20% 0% unidirectional/1024 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. +15% unidirectional/1024 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/1024 unidirectional/1048576 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/1048576 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/1048576 unidirectional/16384 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/16384 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/16384 unidirectional/262144 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/262144 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. +3% unidirectional/262144 unidirectional/4096 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/4096 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/4096 unidirectional/65536 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/65536 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/65536 unidirectional_lockless/1024 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/1024 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/1024 unidirectional_lockless/1048576 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/1048576 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/1048576 unidirectional_lockless/16384 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/16384 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/16384 unidirectional_lockless/262144 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/262144 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/262144 unidirectional_lockless/4096 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/4096 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/4096 unidirectional_lockless/65536 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. -17% unidirectional_lockless/65536 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. -5% unidirectional_lockless/65536
Detailed results
Benchmark Implementation Median CV vs asio

unidirectional/1024

corosio (epoll)

297.9 MB/s

0.91%

+14.9%

unidirectional/1024

asio (coroutines, epoll)

246.8 MB/s

4.13%

-4.8%

unidirectional/1024

asio (callbacks, epoll)

259.4 MB/s

3.66%

baseline (epoll)

unidirectional/1048576

corosio (epoll)

3.28 GB/s

1.83%

-1.9%

unidirectional/1048576

asio (coroutines, epoll)

3.35 GB/s

1.92%

+0.2%

unidirectional/1048576

asio (callbacks, epoll)

3.35 GB/s

2.41%

baseline (epoll)

unidirectional/16384

corosio (epoll)

3.08 GB/s

2.78%

+5.0%

unidirectional/16384

asio (coroutines, epoll)

2.81 GB/s

2.88%

-3.9%

unidirectional/16384

asio (callbacks, epoll)

2.93 GB/s

2.43%

baseline (epoll)

unidirectional/262144

corosio (epoll)

3.36 GB/s

1.72%

+0.3%

unidirectional/262144

asio (coroutines, epoll)

3.45 GB/s

2.07%

+2.9%

unidirectional/262144

asio (callbacks, epoll)

3.35 GB/s

2.04%

baseline (epoll)

unidirectional/4096

corosio (epoll)

980.9 MB/s

0.47%

+8.3%

unidirectional/4096

asio (coroutines, epoll)

862.6 MB/s

2.39%

-4.7%

unidirectional/4096

asio (callbacks, epoll)

905.6 MB/s

2.69%

baseline (epoll)

unidirectional/65536

corosio (epoll)

3.27 GB/s

2.39%

-14.3%

unidirectional/65536

asio (coroutines, epoll)

3.77 GB/s

4.67%

-1.3%

unidirectional/65536

asio (callbacks, epoll)

3.82 GB/s

3.57%

baseline (epoll)

unidirectional_lockless/1024

corosio (epoll)

298.6 MB/s

0.92%

+12.9%

unidirectional_lockless/1024

asio (coroutines, epoll)

252.6 MB/s

4.10%

-4.5%

unidirectional_lockless/1024

asio (callbacks, epoll)

264.5 MB/s

5.34%

baseline (epoll)

unidirectional_lockless/1048576

corosio (epoll)

3.33 GB/s

2.12%

-1.0%

unidirectional_lockless/1048576

asio (coroutines, epoll)

3.35 GB/s

2.35%

-0.5%

unidirectional_lockless/1048576

asio (callbacks, epoll)

3.37 GB/s

1.84%

baseline (epoll)

unidirectional_lockless/16384

corosio (epoll)

3.12 GB/s

4.17%

+6.4%

unidirectional_lockless/16384

asio (coroutines, epoll)

2.85 GB/s

2.32%

-3.0%

unidirectional_lockless/16384

asio (callbacks, epoll)

2.94 GB/s

3.19%

baseline (epoll)

unidirectional_lockless/262144

corosio (epoll)

3.38 GB/s

2.70%

+0.7%

unidirectional_lockless/262144

asio (coroutines, epoll)

3.45 GB/s

3.31%

+2.6%

unidirectional_lockless/262144

asio (callbacks, epoll)

3.36 GB/s

2.33%

baseline (epoll)

unidirectional_lockless/4096

corosio (epoll)

985.3 MB/s

0.79%

+7.4%

unidirectional_lockless/4096

asio (coroutines, epoll)

875.7 MB/s

2.57%

-4.5%

unidirectional_lockless/4096

asio (callbacks, epoll)

917.3 MB/s

2.68%

baseline (epoll)

unidirectional_lockless/65536

corosio (epoll)

3.28 GB/s

1.50%

-17.5%

unidirectional_lockless/65536

asio (coroutines, epoll)

3.77 GB/s

3.03%

-5.2%

unidirectional_lockless/65536

asio (callbacks, epoll)

3.98 GB/s

5.48%

baseline (epoll)


socket_latency

Round-trip latency of a TCP loopback connection. Each sample is one full round trip (request out, reply back) across message sizes and concurrent pair counts.

io_uring

socket_latency (io_uring) — Linux ↑ faster (lower mean latency) · dotted line = asio (callbacks) · backend = io_uring corosio asio (coroutines) -10% +10% +20% +30% 0% concurrent/1 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/1 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/1 concurrent/16 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/16 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/16 concurrent/4 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/4 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/4 concurrent_lockless/1 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. concurrent_lockless/1 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. concurrent_lockless/1 concurrent_lockless/16 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. -1% concurrent_lockless/16 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. concurrent_lockless/16 concurrent_lockless/4 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. concurrent_lockless/4 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. -4% concurrent_lockless/4 pingpong/1 — One TCP connection ping-pongs a message client->server->client; N is the message size in bytes. pingpong/1 — One TCP connection ping-pongs a message client->server->client; N is the message size in bytes. pingpong/1 pingpong/1024 — One TCP connection ping-pongs a message client->server->client; N is the message size in bytes. pingpong/1024 — One TCP connection ping-pongs a message client->server->client; N is the message size in bytes. pingpong/1024 pingpong/64 — One TCP connection ping-pongs a message client->server->client; N is the message size in bytes. +17% pingpong/64 — One TCP connection ping-pongs a message client->server->client; N is the message size in bytes. -2% pingpong/64 pingpong_lockless/1 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/1 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/1 pingpong_lockless/1024 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/1024 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/1024 pingpong_lockless/64 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/64 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/64
Detailed results
Benchmark Implementation Median CV vs asio

concurrent/1

corosio (io_uring)

13.64 µs

0.06%

+17.4%

concurrent/1

asio (coroutines, io_uring)

16.83 µs

0.24%

-1.9%

concurrent/1

asio (callbacks, io_uring)

16.51 µs

0.93%

baseline (io_uring)

concurrent/16

corosio (io_uring)

220.44 µs

0.10%

+2.9%

concurrent/16

asio (coroutines, io_uring)

230.83 µs

0.92%

-1.7%

concurrent/16

asio (callbacks, io_uring)

226.97 µs

1.25%

baseline (io_uring)

concurrent/4

corosio (io_uring)

54.69 µs

0.10%

+6.6%

concurrent/4

asio (coroutines, io_uring)

59.74 µs

0.92%

-2.1%

concurrent/4

asio (callbacks, io_uring)

58.53 µs

1.22%

baseline (io_uring)

concurrent_lockless/1

corosio (io_uring)

13.61 µs

0.24%

+15.7%

concurrent_lockless/1

asio (coroutines, io_uring)

16.49 µs

0.91%

-2.2%

concurrent_lockless/1

asio (callbacks, io_uring)

16.13 µs

1.38%

baseline (io_uring)

concurrent_lockless/16

corosio (io_uring)

219.73 µs

0.93%

-0.6%

concurrent_lockless/16

asio (coroutines, io_uring)

227.94 µs

0.78%

-4.3%

concurrent_lockless/16

asio (callbacks, io_uring)

218.51 µs

1.54%

baseline (io_uring)

concurrent_lockless/4

corosio (io_uring)

54.63 µs

0.77%

+3.2%

concurrent_lockless/4

asio (coroutines, io_uring)

58.89 µs

0.97%

-4.4%

concurrent_lockless/4

asio (callbacks, io_uring)

56.43 µs

1.31%

baseline (io_uring)

pingpong/1

corosio (io_uring)

13.59 µs

0.82%

+17.3%

pingpong/1

asio (coroutines, io_uring)

16.72 µs

1.10%

-1.7%

pingpong/1

asio (callbacks, io_uring)

16.44 µs

1.04%

baseline (io_uring)

pingpong/1024

corosio (io_uring)

13.91 µs

1.06%

+17.2%

pingpong/1024

asio (coroutines, io_uring)

17.10 µs

1.24%

-1.8%

pingpong/1024

asio (callbacks, io_uring)

16.80 µs

1.08%

baseline (io_uring)

pingpong/64

corosio (io_uring)

13.65 µs

0.99%

+17.5%

pingpong/64

asio (coroutines, io_uring)

16.79 µs

1.05%

-1.5%

pingpong/64

asio (callbacks, io_uring)

16.54 µs

1.08%

baseline (io_uring)

pingpong_lockless/1

corosio (io_uring)

13.55 µs

0.90%

+15.9%

pingpong_lockless/1

asio (coroutines, io_uring)

16.45 µs

0.99%

-2.0%

pingpong_lockless/1

asio (callbacks, io_uring)

16.12 µs

0.76%

baseline (io_uring)

pingpong_lockless/1024

corosio (io_uring)

13.85 µs

0.25%

+15.9%

pingpong_lockless/1024

asio (coroutines, io_uring)

16.81 µs

1.01%

-2.1%

pingpong_lockless/1024

asio (callbacks, io_uring)

16.47 µs

0.82%

baseline (io_uring)

pingpong_lockless/64

corosio (io_uring)

13.60 µs

0.83%

+16.0%

pingpong_lockless/64

asio (coroutines, io_uring)

16.53 µs

0.96%

-2.1%

pingpong_lockless/64

asio (callbacks, io_uring)

16.19 µs

1.09%

baseline (io_uring)

epoll

socket_latency (epoll) — Linux ↑ faster (lower mean latency) · dotted line = asio (callbacks) · backend = epoll corosio asio (coroutines) -10% -5% +5% +10% 0% concurrent/1 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. +6% concurrent/1 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. -2% concurrent/1 concurrent/16 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/16 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/16 concurrent/4 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/4 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs. concurrent/4 concurrent_lockless/1 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. concurrent_lockless/1 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. concurrent_lockless/1 concurrent_lockless/16 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. -4% concurrent_lockless/16 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. -3% concurrent_lockless/16 concurrent_lockless/4 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. concurrent_lockless/4 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs. concurrent_lockless/4 pingpong/1 — One TCP connection ping-pongs a message client->server->client; N is the message size in bytes. pingpong/1 — One TCP connection ping-pongs a message client->server->client; N is the message size in bytes. pingpong/1 pingpong/1024 — One TCP connection ping-pongs a message client->server->client; N is the message size in bytes. pingpong/1024 — One TCP connection ping-pongs a message client->server->client; N is the message size in bytes. pingpong/1024 pingpong/64 — One TCP connection ping-pongs a message client->server->client; N is the message size in bytes. pingpong/64 — One TCP connection ping-pongs a message client->server->client; N is the message size in bytes. pingpong/64 pingpong_lockless/1 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/1 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/1 pingpong_lockless/1024 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/1024 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/1024 pingpong_lockless/64 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/64 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes. pingpong_lockless/64
Detailed results
Benchmark Implementation Median CV vs asio

concurrent/1

corosio (epoll)

14.80 µs

0.82%

+5.8%

concurrent/1

asio (coroutines, epoll)

16.05 µs

0.72%

-2.1%

concurrent/1

asio (callbacks, epoll)

15.71 µs

0.06%

baseline (epoll)

concurrent/16

corosio (epoll)

233.52 µs

1.19%

-3.8%

concurrent/16

asio (coroutines, epoll)

231.80 µs

0.43%

-3.0%

concurrent/16

asio (callbacks, epoll)

224.99 µs

0.17%

baseline (epoll)

concurrent/4

corosio (epoll)

58.30 µs

1.07%

-1.6%

concurrent/4

asio (coroutines, epoll)

59.05 µs

0.82%

-2.9%

concurrent/4

asio (callbacks, epoll)

57.37 µs

0.06%

baseline (epoll)

concurrent_lockless/1

corosio (epoll)

14.72 µs

1.25%

+5.0%

concurrent_lockless/1

asio (coroutines, epoll)

15.90 µs

0.22%

-2.6%

concurrent_lockless/1

asio (callbacks, epoll)

15.50 µs

0.19%

baseline (epoll)

concurrent_lockless/16

corosio (epoll)

231.78 µs

1.04%

-4.3%

concurrent_lockless/16

asio (coroutines, epoll)

229.64 µs

1.02%

-3.3%

concurrent_lockless/16

asio (callbacks, epoll)

222.33 µs

1.00%

baseline (epoll)

concurrent_lockless/4

corosio (epoll)

57.95 µs

1.08%

-2.1%

concurrent_lockless/4

asio (coroutines, epoll)

58.46 µs

0.77%

-3.0%

concurrent_lockless/4

asio (callbacks, epoll)

56.75 µs

0.69%

baseline (epoll)

pingpong/1

corosio (epoll)

14.80 µs

1.14%

+5.4%

pingpong/1

asio (coroutines, epoll)

15.99 µs

1.24%

-2.2%

pingpong/1

asio (callbacks, epoll)

15.64 µs

0.58%

baseline (epoll)

pingpong/1024

corosio (epoll)

15.15 µs

0.55%

+5.2%

pingpong/1024

asio (coroutines, epoll)

16.37 µs

1.20%

-2.5%

pingpong/1024

asio (callbacks, epoll)

15.98 µs

0.92%

baseline (epoll)

pingpong/64

corosio (epoll)

14.86 µs

1.13%

+5.4%

pingpong/64

asio (coroutines, epoll)

16.08 µs

1.41%

-2.4%

pingpong/64

asio (callbacks, epoll)

15.71 µs

0.94%

baseline (epoll)

pingpong_lockless/1

corosio (epoll)

14.69 µs

0.34%

+4.9%

pingpong_lockless/1

asio (coroutines, epoll)

15.78 µs

1.02%

-2.2%

pingpong_lockless/1

asio (callbacks, epoll)

15.45 µs

0.91%

baseline (epoll)

pingpong_lockless/1024

corosio (epoll)

15.01 µs

0.45%

+4.6%

pingpong_lockless/1024

asio (coroutines, epoll)

16.11 µs

0.82%

-2.4%

pingpong_lockless/1024

asio (callbacks, epoll)

15.74 µs

0.29%

baseline (epoll)

pingpong_lockless/64

corosio (epoll)

14.74 µs

0.23%

+4.8%

pingpong_lockless/64

asio (coroutines, epoll)

15.85 µs

1.01%

-2.3%

pingpong_lockless/64

asio (callbacks, epoll)

15.48 µs

0.90%

baseline (epoll)


socket_throughput

Sustained byte throughput of a TCP loopback connection under continuous streaming, varying chunk size, direction, and concurrency.

io_uring

socket_throughput (io_uring) — Linux, part 1 ↑ faster · dotted line = asio (callbacks) · backend = io_uring corosio asio (coroutines) -10% +10% +20% 0% bidirectional/1024 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/1024 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/1024 bidirectional/1048576 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/1048576 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/1048576 bidirectional/16384 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/16384 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/16384 bidirectional/262144 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/262144 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/262144 bidirectional/4096 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/4096 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/4096 bidirectional/65536 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/65536 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. -4% bidirectional/65536 bidirectional_lockless/1024 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/1024 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/1024 bidirectional_lockless/1048576 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/1048576 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/1048576 bidirectional_lockless/16384 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. -2% bidirectional_lockless/16384 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/16384 bidirectional_lockless/262144 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/262144 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/262144 bidirectional_lockless/4096 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/4096 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/4096 bidirectional_lockless/65536 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. +12% bidirectional_lockless/65536 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. +2% bidirectional_lockless/65536
Detailed results
Benchmark Implementation Median CV vs asio

bidirectional/1024

corosio (io_uring)

150.7 MB/s

1.28%

+9.6%

bidirectional/1024

asio (coroutines, io_uring)

135.7 MB/s

1.11%

-1.3%

bidirectional/1024

asio (callbacks, io_uring)

137.4 MB/s

1.05%

baseline (io_uring)

bidirectional/1048576

corosio (io_uring)

3.33 GB/s

1.10%

+0.7%

bidirectional/1048576

asio (coroutines, io_uring)

3.30 GB/s

0.50%

-0.1%

bidirectional/1048576

asio (callbacks, io_uring)

3.31 GB/s

0.29%

baseline (io_uring)

bidirectional/16384

corosio (io_uring)

1.62 GB/s

0.97%

-2.1%

bidirectional/16384

asio (coroutines, io_uring)

1.62 GB/s

1.28%

-1.8%

bidirectional/16384

asio (callbacks, io_uring)

1.65 GB/s

2.23%

baseline (io_uring)

bidirectional/262144

corosio (io_uring)

3.29 GB/s

1.40%

+10.4%

bidirectional/262144

asio (coroutines, io_uring)

2.95 GB/s

1.54%

-1.1%

bidirectional/262144

asio (callbacks, io_uring)

2.98 GB/s

1.72%

baseline (io_uring)

bidirectional/4096

corosio (io_uring)

523.6 MB/s

0.98%

+5.5%

bidirectional/4096

asio (coroutines, io_uring)

488.6 MB/s

1.10%

-1.6%

bidirectional/4096

asio (callbacks, io_uring)

496.3 MB/s

1.33%

baseline (io_uring)

bidirectional/65536

corosio (io_uring)

2.89 GB/s

1.43%

+8.9%

bidirectional/65536

asio (coroutines, io_uring)

2.54 GB/s

1.44%

-4.1%

bidirectional/65536

asio (callbacks, io_uring)

2.65 GB/s

1.88%

baseline (io_uring)

bidirectional_lockless/1024

corosio (io_uring)

150.6 MB/s

0.29%

+8.0%

bidirectional_lockless/1024

asio (coroutines, io_uring)

137.4 MB/s

1.07%

-1.5%

bidirectional_lockless/1024

asio (callbacks, io_uring)

139.5 MB/s

1.07%

baseline (io_uring)

bidirectional_lockless/1048576

corosio (io_uring)

3.33 GB/s

1.53%

+0.9%

bidirectional_lockless/1048576

asio (coroutines, io_uring)

3.29 GB/s

0.78%

-0.3%

bidirectional_lockless/1048576

asio (callbacks, io_uring)

3.30 GB/s

1.18%

baseline (io_uring)

bidirectional_lockless/16384

corosio (io_uring)

1.63 GB/s

0.79%

-2.2%

bidirectional_lockless/16384

asio (coroutines, io_uring)

1.67 GB/s

2.07%

+0.5%

bidirectional_lockless/16384

asio (callbacks, io_uring)

1.66 GB/s

1.39%

baseline (io_uring)

bidirectional_lockless/262144

corosio (io_uring)

3.24 GB/s

1.53%

+10.4%

bidirectional_lockless/262144

asio (coroutines, io_uring)

2.97 GB/s

1.16%

+1.3%

bidirectional_lockless/262144

asio (callbacks, io_uring)

2.93 GB/s

1.34%

baseline (io_uring)

bidirectional_lockless/4096

corosio (io_uring)

523.0 MB/s

0.35%

+4.0%

bidirectional_lockless/4096

asio (coroutines, io_uring)

494.5 MB/s

0.96%

-1.7%

bidirectional_lockless/4096

asio (callbacks, io_uring)

502.9 MB/s

1.43%

baseline (io_uring)

bidirectional_lockless/65536

corosio (io_uring)

2.87 GB/s

1.41%

+11.7%

bidirectional_lockless/65536

asio (coroutines, io_uring)

2.61 GB/s

2.20%

+1.7%

bidirectional_lockless/65536

asio (callbacks, io_uring)

2.57 GB/s

1.89%

baseline (io_uring)

socket_throughput (io_uring) — Linux, part 2 ↑ faster · dotted line = asio (callbacks) · backend = io_uring corosio asio (coroutines) -100% +100% +200% +300% +400% 0% multithread/2 — 32 bidirectional connection pairs share one context serviced by N threads running the context, with 64 KiB chunks; N is the thread count. +149% multithread/2 — 32 bidirectional connection pairs share one context serviced by N threads running the context, with 64 KiB chunks; N is the thread count. +13% multithread/2 multithread/4 — 32 bidirectional connection pairs share one context serviced by N threads running the context, with 64 KiB chunks; N is the thread count. +282% multithread/4 — 32 bidirectional connection pairs share one context serviced by N threads running the context, with 64 KiB chunks; N is the thread count. 0% multithread/4 multithread/8 — 32 bidirectional connection pairs share one context serviced by N threads running the context, with 64 KiB chunks; N is the thread count. +292% multithread/8 — 32 bidirectional connection pairs share one context serviced by N threads running the context, with 64 KiB chunks; N is the thread count. -1% multithread/8
Detailed results
Benchmark Implementation Median CV vs asio

multithread/2

corosio (io_uring)

4.17 GB/s

0.37%

+149.4%

multithread/2

asio (coroutines, io_uring)

1.89 GB/s

7.50%

+12.7%

multithread/2

asio (callbacks, io_uring)

1.67 GB/s

5.49%

baseline (io_uring)

multithread/4

corosio (io_uring)

6.51 GB/s

0.43%

+281.7%

multithread/4

asio (coroutines, io_uring)

1.70 GB/s

0.73%

-0.3%

multithread/4

asio (callbacks, io_uring)

1.71 GB/s

0.88%

baseline (io_uring)

multithread/8

corosio (io_uring)

6.64 GB/s

0.54%

+292.0%

multithread/8

asio (coroutines, io_uring)

1.67 GB/s

0.99%

-1.4%

multithread/8

asio (callbacks, io_uring)

1.69 GB/s

0.59%

baseline (io_uring)

socket_throughput (io_uring) — Linux, part 3 ↑ faster · dotted line = asio (callbacks) · backend = io_uring corosio asio (coroutines) -25% +25% +50% +75% 0% unidirectional/1024 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. +61% unidirectional/1024 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/1024 unidirectional/1048576 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/1048576 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/1048576 unidirectional/16384 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/16384 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/16384 unidirectional/262144 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/262144 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/262144 unidirectional/4096 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/4096 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/4096 unidirectional/65536 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/65536 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/65536 unidirectional_lockless/1024 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/1024 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/1024 unidirectional_lockless/1048576 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. -4% unidirectional_lockless/1048576 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/1048576 unidirectional_lockless/16384 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/16384 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/16384 unidirectional_lockless/262144 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/262144 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. +1% unidirectional_lockless/262144 unidirectional_lockless/4096 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/4096 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/4096 unidirectional_lockless/65536 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/65536 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. -3% unidirectional_lockless/65536
Detailed results
Benchmark Implementation Median CV vs asio

unidirectional/1024

corosio (io_uring)

148.8 MB/s

1.02%

+61.0%

unidirectional/1024

asio (coroutines, io_uring)

91.67 MB/s

1.39%

-0.9%

unidirectional/1024

asio (callbacks, io_uring)

92.46 MB/s

1.21%

baseline (io_uring)

unidirectional/1048576

corosio (io_uring)

3.41 GB/s

0.92%

+0.5%

unidirectional/1048576

asio (coroutines, io_uring)

3.36 GB/s

3.10%

-1.0%

unidirectional/1048576

asio (callbacks, io_uring)

3.39 GB/s

2.44%

baseline (io_uring)

unidirectional/16384

corosio (io_uring)

1.71 GB/s

2.91%

+28.0%

unidirectional/16384

asio (coroutines, io_uring)

1.33 GB/s

1.44%

-0.5%

unidirectional/16384

asio (callbacks, io_uring)

1.34 GB/s

2.03%

baseline (io_uring)

unidirectional/262144

corosio (io_uring)

3.23 GB/s

1.26%

+3.0%

unidirectional/262144

asio (coroutines, io_uring)

3.14 GB/s

1.65%

+0.1%

unidirectional/262144

asio (callbacks, io_uring)

3.14 GB/s

1.71%

baseline (io_uring)

unidirectional/4096

corosio (io_uring)

521.4 MB/s

0.87%

+44.6%

unidirectional/4096

asio (coroutines, io_uring)

357.8 MB/s

1.49%

-0.8%

unidirectional/4096

asio (callbacks, io_uring)

360.6 MB/s

1.39%

baseline (io_uring)

unidirectional/65536

corosio (io_uring)

2.80 GB/s

1.28%

+4.0%

unidirectional/65536

asio (coroutines, io_uring)

2.67 GB/s

0.66%

-1.0%

unidirectional/65536

asio (callbacks, io_uring)

2.69 GB/s

2.48%

baseline (io_uring)

unidirectional_lockless/1024

corosio (io_uring)

149.7 MB/s

0.97%

+59.7%

unidirectional_lockless/1024

asio (coroutines, io_uring)

92.57 MB/s

0.42%

-1.3%

unidirectional_lockless/1024

asio (callbacks, io_uring)

93.76 MB/s

1.03%

baseline (io_uring)

unidirectional_lockless/1048576

corosio (io_uring)

3.40 GB/s

1.19%

-4.1%

unidirectional_lockless/1048576

asio (coroutines, io_uring)

3.54 GB/s

0.50%

+0.0%

unidirectional_lockless/1048576

asio (callbacks, io_uring)

3.54 GB/s

2.32%

baseline (io_uring)

unidirectional_lockless/16384

corosio (io_uring)

1.72 GB/s

1.61%

+26.7%

unidirectional_lockless/16384

asio (coroutines, io_uring)

1.34 GB/s

1.66%

-1.3%

unidirectional_lockless/16384

asio (callbacks, io_uring)

1.36 GB/s

0.99%

baseline (io_uring)

unidirectional_lockless/262144

corosio (io_uring)

3.31 GB/s

1.29%

+5.6%

unidirectional_lockless/262144

asio (coroutines, io_uring)

3.17 GB/s

1.39%

+1.3%

unidirectional_lockless/262144

asio (callbacks, io_uring)

3.13 GB/s

0.78%

baseline (io_uring)

unidirectional_lockless/4096

corosio (io_uring)

518.1 MB/s

1.43%

+41.7%

unidirectional_lockless/4096

asio (coroutines, io_uring)

360.6 MB/s

0.57%

-1.4%

unidirectional_lockless/4096

asio (callbacks, io_uring)

365.7 MB/s

1.01%

baseline (io_uring)

unidirectional_lockless/65536

corosio (io_uring)

2.81 GB/s

2.08%

+1.7%

unidirectional_lockless/65536

asio (coroutines, io_uring)

2.69 GB/s

4.08%

-2.8%

unidirectional_lockless/65536

asio (callbacks, io_uring)

2.76 GB/s

2.76%

baseline (io_uring)

epoll

socket_throughput (epoll) — Linux, part 1 ↑ faster · dotted line = asio (callbacks) · backend = epoll corosio asio (coroutines) -10% +10% +20% 0% bidirectional/1024 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/1024 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/1024 bidirectional/1048576 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/1048576 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/1048576 bidirectional/16384 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/16384 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/16384 bidirectional/262144 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. +9% bidirectional/262144 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/262144 bidirectional/4096 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/4096 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/4096 bidirectional/65536 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/65536 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes. bidirectional/65536 bidirectional_lockless/1024 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. -6% bidirectional_lockless/1024 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/1024 bidirectional_lockless/1048576 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/1048576 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. +0% bidirectional_lockless/1048576 bidirectional_lockless/16384 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/16384 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/16384 bidirectional_lockless/262144 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/262144 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/262144 bidirectional_lockless/4096 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/4096 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. -4% bidirectional_lockless/4096 bidirectional_lockless/65536 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/65536 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. bidirectional_lockless/65536
Detailed results
Benchmark Implementation Median CV vs asio

bidirectional/1024

corosio (epoll)

133.5 MB/s

0.24%

-5.6%

bidirectional/1024

asio (coroutines, epoll)

137.4 MB/s

0.13%

-2.9%

bidirectional/1024

asio (callbacks, epoll)

141.5 MB/s

0.10%

baseline (epoll)

bidirectional/1048576

corosio (epoll)

3.28 GB/s

0.96%

-1.3%

bidirectional/1048576

asio (coroutines, epoll)

3.32 GB/s

0.86%

+0.0%

bidirectional/1048576

asio (callbacks, epoll)

3.32 GB/s

1.26%

baseline (epoll)

bidirectional/16384

corosio (epoll)

1.63 GB/s

0.71%

-2.9%

bidirectional/16384

asio (coroutines, epoll)

1.64 GB/s

0.75%

-2.6%

bidirectional/16384

asio (callbacks, epoll)

1.68 GB/s

1.18%

baseline (epoll)

bidirectional/262144

corosio (epoll)

3.26 GB/s

0.90%

+9.5%

bidirectional/262144

asio (coroutines, epoll)

2.96 GB/s

0.59%

-0.4%

bidirectional/262144

asio (callbacks, epoll)

2.97 GB/s

0.82%

baseline (epoll)

bidirectional/4096

corosio (epoll)

503.3 MB/s

0.59%

-1.5%

bidirectional/4096

asio (coroutines, epoll)

494.4 MB/s

0.45%

-3.2%

bidirectional/4096

asio (callbacks, epoll)

510.7 MB/s

0.23%

baseline (epoll)

bidirectional/65536

corosio (epoll)

2.65 GB/s

2.26%

+0.7%

bidirectional/65536

asio (coroutines, epoll)

2.61 GB/s

1.34%

-0.8%

bidirectional/65536

asio (callbacks, epoll)

2.63 GB/s

1.13%

baseline (epoll)

bidirectional_lockless/1024

corosio (epoll)

134.4 MB/s

0.70%

-6.0%

bidirectional_lockless/1024

asio (coroutines, epoll)

138.7 MB/s

1.02%

-3.0%

bidirectional_lockless/1024

asio (callbacks, epoll)

143.0 MB/s

1.00%

baseline (epoll)

bidirectional_lockless/1048576

corosio (epoll)

3.30 GB/s

2.14%

-0.2%

bidirectional_lockless/1048576

asio (coroutines, epoll)

3.32 GB/s

0.80%

+0.3%

bidirectional_lockless/1048576

asio (callbacks, epoll)

3.31 GB/s

0.88%

baseline (epoll)

bidirectional_lockless/16384

corosio (epoll)

1.65 GB/s

1.60%

-4.6%

bidirectional_lockless/16384

asio (coroutines, epoll)

1.66 GB/s

1.78%

-3.7%

bidirectional_lockless/16384

asio (callbacks, epoll)

1.73 GB/s

1.74%

baseline (epoll)

bidirectional_lockless/262144

corosio (epoll)

3.22 GB/s

0.76%

+8.3%

bidirectional_lockless/262144

asio (coroutines, epoll)

2.95 GB/s

1.25%

-0.8%

bidirectional_lockless/262144

asio (callbacks, epoll)

2.98 GB/s

0.95%

baseline (epoll)

bidirectional_lockless/4096

corosio (epoll)

506.9 MB/s

1.12%

-1.9%

bidirectional_lockless/4096

asio (coroutines, epoll)

497.4 MB/s

1.18%

-3.7%

bidirectional_lockless/4096

asio (callbacks, epoll)

516.7 MB/s

0.94%

baseline (epoll)

bidirectional_lockless/65536

corosio (epoll)

2.57 GB/s

2.44%

-3.3%

bidirectional_lockless/65536

asio (coroutines, epoll)

2.60 GB/s

1.50%

-2.3%

bidirectional_lockless/65536

asio (callbacks, epoll)

2.66 GB/s

1.44%

baseline (epoll)

socket_throughput (epoll) — Linux, part 2 ↑ faster · dotted line = asio (callbacks) · backend = epoll corosio asio (coroutines) -20% +20% +40% +60% 0% multithread/2 — 32 bidirectional connection pairs share one context serviced by N threads running the context, with 64 KiB chunks; N is the thread count. +49% multithread/2 — 32 bidirectional connection pairs share one context serviced by N threads running the context, with 64 KiB chunks; N is the thread count. -3% multithread/2 multithread/4 — 32 bidirectional connection pairs share one context serviced by N threads running the context, with 64 KiB chunks; N is the thread count. +43% multithread/4 — 32 bidirectional connection pairs share one context serviced by N threads running the context, with 64 KiB chunks; N is the thread count. +0% multithread/4 multithread/8 — 32 bidirectional connection pairs share one context serviced by N threads running the context, with 64 KiB chunks; N is the thread count. +27% multithread/8 — 32 bidirectional connection pairs share one context serviced by N threads running the context, with 64 KiB chunks; N is the thread count. 0% multithread/8
Detailed results
Benchmark Implementation Median CV vs asio

multithread/2

corosio (epoll)

3.71 GB/s

0.71%

+49.3%

multithread/2

asio (coroutines, epoll)

2.40 GB/s

1.76%

-3.4%

multithread/2

asio (callbacks, epoll)

2.49 GB/s

2.09%

baseline (epoll)

multithread/4

corosio (epoll)

5.81 GB/s

0.61%

+42.6%

multithread/4

asio (coroutines, epoll)

4.08 GB/s

0.50%

+0.1%

multithread/4

asio (callbacks, epoll)

4.08 GB/s

0.44%

baseline (epoll)

multithread/8

corosio (epoll)

6.23 GB/s

0.39%

+26.7%

multithread/8

asio (coroutines, epoll)

4.90 GB/s

0.58%

-0.4%

multithread/8

asio (callbacks, epoll)

4.92 GB/s

0.41%

baseline (epoll)

socket_throughput (epoll) — Linux, part 3 ↑ faster · dotted line = asio (callbacks) · backend = epoll corosio asio (coroutines) -20% +20% +40% 0% unidirectional/1024 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/1024 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/1024 unidirectional/1048576 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/1048576 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. +0% unidirectional/1048576 unidirectional/16384 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/16384 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/16384 unidirectional/262144 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/262144 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/262144 unidirectional/4096 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/4096 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/4096 unidirectional/65536 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/65536 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes. unidirectional/65536 unidirectional_lockless/1024 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. +33% unidirectional_lockless/1024 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/1024 unidirectional_lockless/1048576 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. -7% unidirectional_lockless/1048576 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/1048576 unidirectional_lockless/16384 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/16384 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/16384 unidirectional_lockless/262144 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/262144 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/262144 unidirectional_lockless/4096 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/4096 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/4096 unidirectional_lockless/65536 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. unidirectional_lockless/65536 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes. -3% unidirectional_lockless/65536
Detailed results
Benchmark Implementation Median CV vs asio

unidirectional/1024

corosio (epoll)

125.5 MB/s

1.00%

+32.8%

unidirectional/1024

asio (coroutines, epoll)

92.74 MB/s

1.25%

-1.9%

unidirectional/1024

asio (callbacks, epoll)

94.50 MB/s

0.21%

baseline (epoll)

unidirectional/1048576

corosio (epoll)

3.39 GB/s

0.40%

-0.4%

unidirectional/1048576

asio (coroutines, epoll)

3.42 GB/s

1.19%

+0.5%

unidirectional/1048576

asio (callbacks, epoll)

3.41 GB/s

1.18%

baseline (epoll)

unidirectional/16384

corosio (epoll)

1.53 GB/s

1.35%

+12.1%

unidirectional/16384

asio (coroutines, epoll)

1.34 GB/s

1.53%

-2.5%

unidirectional/16384

asio (callbacks, epoll)

1.37 GB/s

0.67%

baseline (epoll)

unidirectional/262144

corosio (epoll)

3.33 GB/s

1.33%

+5.1%

unidirectional/262144

asio (coroutines, epoll)

3.17 GB/s

1.52%

+0.1%

unidirectional/262144

asio (callbacks, epoll)

3.17 GB/s

1.01%

baseline (epoll)

unidirectional/4096

corosio (epoll)

469.9 MB/s

1.11%

+27.8%

unidirectional/4096

asio (coroutines, epoll)

361.1 MB/s

1.23%

-1.8%

unidirectional/4096

asio (callbacks, epoll)

367.6 MB/s

0.65%

baseline (epoll)

unidirectional/65536

corosio (epoll)

2.81 GB/s

2.56%

+2.5%

unidirectional/65536

asio (coroutines, epoll)

2.68 GB/s

1.98%

-2.0%

unidirectional/65536

asio (callbacks, epoll)

2.74 GB/s

1.62%

baseline (epoll)

unidirectional_lockless/1024

corosio (epoll)

126.2 MB/s

0.41%

+32.8%

unidirectional_lockless/1024

asio (coroutines, epoll)

93.23 MB/s

0.59%

-1.9%

unidirectional_lockless/1024

asio (callbacks, epoll)

95.07 MB/s

1.12%

baseline (epoll)

unidirectional_lockless/1048576

corosio (epoll)

3.33 GB/s

1.04%

-6.8%

unidirectional_lockless/1048576

asio (coroutines, epoll)

3.57 GB/s

0.60%

-0.2%

unidirectional_lockless/1048576

asio (callbacks, epoll)

3.58 GB/s

0.88%

baseline (epoll)

unidirectional_lockless/16384

corosio (epoll)

1.57 GB/s

1.06%

+12.7%

unidirectional_lockless/16384

asio (coroutines, epoll)

1.35 GB/s

1.65%

-2.8%

unidirectional_lockless/16384

asio (callbacks, epoll)

1.39 GB/s

0.91%

baseline (epoll)

unidirectional_lockless/262144

corosio (epoll)

3.32 GB/s

1.00%

+4.9%

unidirectional_lockless/262144

asio (coroutines, epoll)

3.13 GB/s

1.22%

-1.0%

unidirectional_lockless/262144

asio (callbacks, epoll)

3.16 GB/s

0.91%

baseline (epoll)

unidirectional_lockless/4096

corosio (epoll)

475.0 MB/s

0.89%

+27.8%

unidirectional_lockless/4096

asio (coroutines, epoll)

364.4 MB/s

1.11%

-2.0%

unidirectional_lockless/4096

asio (callbacks, epoll)

371.8 MB/s

1.15%

baseline (epoll)

unidirectional_lockless/65536

corosio (epoll)

2.81 GB/s

4.33%

+2.1%

unidirectional_lockless/65536

asio (coroutines, epoll)

2.66 GB/s

2.33%

-3.5%

unidirectional_lockless/65536

asio (callbacks, epoll)

2.75 GB/s

2.76%

baseline (epoll)