diff --git a/doc/modules/ROOT/images/bench/linux-accept_churn-epoll.svg b/doc/modules/ROOT/images/bench/linux-accept_churn-epoll.svg
index bf72617b0..09d988756 100644
--- a/doc/modules/ROOT/images/bench/linux-accept_churn-epoll.svg
+++ b/doc/modules/ROOT/images/bench/linux-accept_churn-epoll.svg
@@ -8,44 +8,42 @@
asio (coroutines)
--15%
-
--10%
-
--5%
+-10%
+
+-5%
+5%
-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.
--4%
+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.
--13%
-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 — 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 — 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 — 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 — 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 — 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 — 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.
--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.
+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 — 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
-
+
diff --git a/doc/modules/ROOT/images/bench/linux-accept_churn-uring.svg b/doc/modules/ROOT/images/bench/linux-accept_churn-uring.svg
index 9b8e214d2..a9049ca3c 100644
--- a/doc/modules/ROOT/images/bench/linux-accept_churn-uring.svg
+++ b/doc/modules/ROOT/images/bench/linux-accept_churn-uring.svg
@@ -8,44 +8,44 @@
asio (coroutines)
--60%
+-6%
--40%
+-4%
--20%
+-2%
-+20%
++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 — 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.
+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 — 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.
-+0%
+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.
--3%
+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.
--35%
-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 — 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.
-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.
+-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.
-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 — 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.
--22%
-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 — Same as sequential, with the context in single-threaded lockless mode.
+-2%
sequential_lockless
diff --git a/doc/modules/ROOT/images/bench/linux-fan_out-epoll-g1.svg b/doc/modules/ROOT/images/bench/linux-fan_out-epoll-g1.svg
index 469552c13..73adeb7f1 100644
--- a/doc/modules/ROOT/images/bench/linux-fan_out-epoll-g1.svg
+++ b/doc/modules/ROOT/images/bench/linux-fan_out-epoll-g1.svg
@@ -8,43 +8,45 @@
asio (coroutines)
--15%
-
--10%
-
--5%
+-10%
+
+-7.5%
+
+-5%
+
+-2.5%
-+5%
-0%
-concurrent_parents/1 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
--8%
-concurrent_parents/1 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
--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.
--9%
-concurrent_parents/16 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
--5%
+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.
--9%
-concurrent_parents/4 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
--5%
+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.
--8%
-concurrent_parents_lockless/1 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of 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.
--9%
-concurrent_parents_lockless/16 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
--5%
+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.
--9%
-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 — 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
-
+
diff --git a/doc/modules/ROOT/images/bench/linux-fan_out-epoll-g2.svg b/doc/modules/ROOT/images/bench/linux-fan_out-epoll-g2.svg
index 3f597dc84..42d1b2bf7 100644
--- a/doc/modules/ROOT/images/bench/linux-fan_out-epoll-g2.svg
+++ b/doc/modules/ROOT/images/bench/linux-fan_out-epoll-g2.svg
@@ -16,45 +16,45 @@
+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.
--12%
+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 — 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.
--8%
-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 — 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.
+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 — 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 — 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 — 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.
--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 — 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 — 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.
--9%
-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 — 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 — 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
diff --git a/doc/modules/ROOT/images/bench/linux-fan_out-uring-g1.svg b/doc/modules/ROOT/images/bench/linux-fan_out-uring-g1.svg
index b1972783b..8e65f67b3 100644
--- a/doc/modules/ROOT/images/bench/linux-fan_out-uring-g1.svg
+++ b/doc/modules/ROOT/images/bench/linux-fan_out-uring-g1.svg
@@ -8,45 +8,45 @@
asio (coroutines)
--20%
+-6%
--15%
+-4%
--10%
-
--5%
+-2%
+
++2%
-+5%
-0%
-concurrent_parents/1 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
--13%
-concurrent_parents/1 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
--4%
++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.
--13%
-concurrent_parents/16 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
--3%
+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.
--13%
-concurrent_parents/4 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
--3%
+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.
--8%
-concurrent_parents_lockless/1 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of 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.
--9%
-concurrent_parents_lockless/16 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
--3%
+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.
--9%
-concurrent_parents_lockless/4 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
--3%
+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
-
+
diff --git a/doc/modules/ROOT/images/bench/linux-fan_out-uring-g2.svg b/doc/modules/ROOT/images/bench/linux-fan_out-uring-g2.svg
index 672e021ce..e6b60fdb7 100644
--- a/doc/modules/ROOT/images/bench/linux-fan_out-uring-g2.svg
+++ b/doc/modules/ROOT/images/bench/linux-fan_out-uring-g2.svg
@@ -8,51 +8,53 @@
asio (coroutines)
--20%
-
--10%
+-15%
+
+-10%
+
+-5%
-+10%
-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.
--12%
++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 — 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 — 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.
-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.
++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.
-+2%
-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 — 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 — 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 — 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.
--2%
+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.
--16%
-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 — 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 — 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 — 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 — 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
-
+
diff --git a/doc/modules/ROOT/images/bench/linux-http_server-epoll.svg b/doc/modules/ROOT/images/bench/linux-http_server-epoll.svg
index aea3b9430..364ea9d3b 100644
--- a/doc/modules/ROOT/images/bench/linux-http_server-epoll.svg
+++ b/doc/modules/ROOT/images/bench/linux-http_server-epoll.svg
@@ -8,52 +8,50 @@
asio (coroutines)
--10%
-
--7.5%
-
--5%
-
--2.5%
+-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.
+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 — 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 — 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.
--1%
+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 — 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.
--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.
++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.
--8%
-multithread/2 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count.
--5%
+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 — 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 — 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 — 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 — 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
-
+
diff --git a/doc/modules/ROOT/images/bench/linux-http_server-uring.svg b/doc/modules/ROOT/images/bench/linux-http_server-uring.svg
index 637b9de0e..9dd969c1a 100644
--- a/doc/modules/ROOT/images/bench/linux-http_server-uring.svg
+++ b/doc/modules/ROOT/images/bench/linux-http_server-uring.svg
@@ -8,50 +8,48 @@
asio (coroutines)
--50%
-
-+50%
-
-+100%
+-100%
+
++100%
-+150%
-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.
++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 — 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.
--14%
-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 — 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 — 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 — 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.
--7%
+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.
-+91%
-multithread/2 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count.
-0%
+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.
-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.
++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 — 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 — 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 — 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
-
+
diff --git a/doc/modules/ROOT/images/bench/linux-local_socket_latency-epoll.svg b/doc/modules/ROOT/images/bench/linux-local_socket_latency-epoll.svg
index 559275a43..16d1ae29d 100644
--- a/doc/modules/ROOT/images/bench/linux-local_socket_latency-epoll.svg
+++ b/doc/modules/ROOT/images/bench/linux-local_socket_latency-epoll.svg
@@ -18,45 +18,45 @@
+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 — 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 — 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 — 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 — 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.
--8%
-concurrent_lockless/16 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs.
+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.
--8%
+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 — 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.
-+18%
-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.
++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 — 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.
--4%
+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 — 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 — 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
diff --git a/doc/modules/ROOT/images/bench/linux-local_socket_latency-uring.svg b/doc/modules/ROOT/images/bench/linux-local_socket_latency-uring.svg
index 3374638b0..9ca02164d 100644
--- a/doc/modules/ROOT/images/bench/linux-local_socket_latency-uring.svg
+++ b/doc/modules/ROOT/images/bench/linux-local_socket_latency-uring.svg
@@ -14,45 +14,45 @@
+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.
+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 — 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 — 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 — 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.
--11%
-concurrent_lockless/16 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs.
+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 — 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.
-+26%
-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.
++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.
--8%
+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 — 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 — 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.
-+2%
+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 — 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
diff --git a/doc/modules/ROOT/images/bench/linux-local_socket_throughput-epoll-g1.svg b/doc/modules/ROOT/images/bench/linux-local_socket_throughput-epoll-g1.svg
index cf9432f23..2f57e31a7 100644
--- a/doc/modules/ROOT/images/bench/linux-local_socket_throughput-epoll-g1.svg
+++ b/doc/modules/ROOT/images/bench/linux-local_socket_throughput-epoll-g1.svg
@@ -18,45 +18,45 @@
+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.
--11%
+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 — 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 — 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 — 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.
-+8%
-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.
++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 — 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 — 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 — 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 — 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.
-+0%
+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 — 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.
--19%
-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.
+-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
diff --git a/doc/modules/ROOT/images/bench/linux-local_socket_throughput-epoll-g2.svg b/doc/modules/ROOT/images/bench/linux-local_socket_throughput-epoll-g2.svg
index db23ea332..456b7d2df 100644
--- a/doc/modules/ROOT/images/bench/linux-local_socket_throughput-epoll-g2.svg
+++ b/doc/modules/ROOT/images/bench/linux-local_socket_throughput-epoll-g2.svg
@@ -8,51 +8,51 @@
asio (coroutines)
--20%
-
-+20%
+-40%
+
+-20%
-+40%
-0%
-unidirectional/1024 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes.
-+16%
-unidirectional/1024 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes.
--6%
++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 — 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 — 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 — 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 — 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 — 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 — 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 — 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 — 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 — 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 — 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.
--15%
-unidirectional_lockless/65536 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes.
-+1%
+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
-
+
diff --git a/doc/modules/ROOT/images/bench/linux-local_socket_throughput-uring-g1.svg b/doc/modules/ROOT/images/bench/linux-local_socket_throughput-uring-g1.svg
index 1d5eb3dc9..cbd36441f 100644
--- a/doc/modules/ROOT/images/bench/linux-local_socket_throughput-uring-g1.svg
+++ b/doc/modules/ROOT/images/bench/linux-local_socket_throughput-uring-g1.svg
@@ -8,51 +8,51 @@
asio (coroutines)
--40%
-
--20%
+-20%
+
++20%
-+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.
--5%
++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 — 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 — 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 — 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 — 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.
--20%
-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.
+-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 — 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 — 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 — 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 — 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.
-+12%
-bidirectional_lockless/4096 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes.
-+3%
+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 — 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
-
+
diff --git a/doc/modules/ROOT/images/bench/linux-local_socket_throughput-uring-g2.svg b/doc/modules/ROOT/images/bench/linux-local_socket_throughput-uring-g2.svg
index e50aff8c2..ae5a7da83 100644
--- a/doc/modules/ROOT/images/bench/linux-local_socket_throughput-uring-g2.svg
+++ b/doc/modules/ROOT/images/bench/linux-local_socket_throughput-uring-g2.svg
@@ -9,52 +9,54 @@
asio (coroutines)
-40%
-
--20%
-
-+20%
+
+-20%
+
++20%
+
++40%
-+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.
--9%
++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 — 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 — 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 — 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 — 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 — 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.
-+17%
-unidirectional_lockless/1024 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes.
-+3%
+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 — 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 — 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 — 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 — 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.
--18%
-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 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes.
unidirectional_lockless/65536
-
+
diff --git a/doc/modules/ROOT/images/bench/linux-socket_latency-epoll.svg b/doc/modules/ROOT/images/bench/linux-socket_latency-epoll.svg
index b98400290..eb45abebb 100644
--- a/doc/modules/ROOT/images/bench/linux-socket_latency-epoll.svg
+++ b/doc/modules/ROOT/images/bench/linux-socket_latency-epoll.svg
@@ -8,51 +8,53 @@
asio (coroutines)
--5%
-
-+5%
+-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.
-concurrent/1 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs.
+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 — 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 — 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 — 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 — 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.
--3%
+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 — 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.
-+7%
-pingpong/1024 — One TCP connection ping-pongs a message client->server->client; N is the message size in bytes.
--2%
+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 — 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 — 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 — 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 — 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
-
+
diff --git a/doc/modules/ROOT/images/bench/linux-socket_latency-uring.svg b/doc/modules/ROOT/images/bench/linux-socket_latency-uring.svg
index 11a07cb9e..39980a254 100644
--- a/doc/modules/ROOT/images/bench/linux-socket_latency-uring.svg
+++ b/doc/modules/ROOT/images/bench/linux-socket_latency-uring.svg
@@ -9,50 +9,52 @@
asio (coroutines)
-10%
-
-+10%
+
++10%
+
++20%
-+20%
-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.
++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 — 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 — 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 — 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.
--5%
-concurrent_lockless/16 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs.
+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.
+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.
-+13%
-pingpong/1 — One TCP connection ping-pongs a message client->server->client; N is the message size in bytes.
--2%
+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 — 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 — 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 — 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 — 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.
--3%
+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
-
+
diff --git a/doc/modules/ROOT/images/bench/linux-socket_throughput-epoll-g1.svg b/doc/modules/ROOT/images/bench/linux-socket_throughput-epoll-g1.svg
index 6d1a0c13b..a630cf01a 100644
--- a/doc/modules/ROOT/images/bench/linux-socket_throughput-epoll-g1.svg
+++ b/doc/modules/ROOT/images/bench/linux-socket_throughput-epoll-g1.svg
@@ -14,45 +14,45 @@
+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.
--3%
+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 — 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 — 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.
-+13%
-bidirectional/262144 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes.
-+2%
+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 — 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 — 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.
-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.
+-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.
+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 — 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 — 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 — 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.
--5%
-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 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes.
bidirectional_lockless/65536
diff --git a/doc/modules/ROOT/images/bench/linux-socket_throughput-epoll-g2.svg b/doc/modules/ROOT/images/bench/linux-socket_throughput-epoll-g2.svg
index e49dadd23..fbaa3d664 100644
--- a/doc/modules/ROOT/images/bench/linux-socket_throughput-epoll-g2.svg
+++ b/doc/modules/ROOT/images/bench/linux-socket_throughput-epoll-g2.svg
@@ -16,20 +16,20 @@
+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.
-+45%
-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 — 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.
-+38%
-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 — 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.
-+25%
-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 — 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
diff --git a/doc/modules/ROOT/images/bench/linux-socket_throughput-epoll-g3.svg b/doc/modules/ROOT/images/bench/linux-socket_throughput-epoll-g3.svg
index 7648aecff..295ab8efe 100644
--- a/doc/modules/ROOT/images/bench/linux-socket_throughput-epoll-g3.svg
+++ b/doc/modules/ROOT/images/bench/linux-socket_throughput-epoll-g3.svg
@@ -9,52 +9,50 @@
asio (coroutines)
-20%
-
-+20%
-
-+40%
+
++20%
-+60%
-0%
-unidirectional/1024 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes.
-+35%
-unidirectional/1024 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes.
++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.
+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.
--3%
+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 — 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 — 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 — 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 — 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.
--6%
-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.
+-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 — 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 — 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 — 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.
-+0%
+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
-
+
diff --git a/doc/modules/ROOT/images/bench/linux-socket_throughput-uring-g1.svg b/doc/modules/ROOT/images/bench/linux-socket_throughput-uring-g1.svg
index 7b827b4ab..63b7ccbb2 100644
--- a/doc/modules/ROOT/images/bench/linux-socket_throughput-uring-g1.svg
+++ b/doc/modules/ROOT/images/bench/linux-socket_throughput-uring-g1.svg
@@ -8,53 +8,51 @@
asio (coroutines)
--20%
-
--10%
-
-+10%
+-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.
+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 — 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.
--5%
+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 — 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 — 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 — 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 — 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 — 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.
--8%
-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.
+-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.
-+13%
-bidirectional_lockless/262144 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes.
-+1%
+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 — 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 — 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
-
+
diff --git a/doc/modules/ROOT/images/bench/linux-socket_throughput-uring-g2.svg b/doc/modules/ROOT/images/bench/linux-socket_throughput-uring-g2.svg
index e348a6c0e..03198195c 100644
--- a/doc/modules/ROOT/images/bench/linux-socket_throughput-uring-g2.svg
+++ b/doc/modules/ROOT/images/bench/linux-socket_throughput-uring-g2.svg
@@ -9,27 +9,29 @@
asio (coroutines)
-100%
-
-+100%
-
-+200%
+
++100%
+
++200%
+
++300%
-+300%
-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.
-+123%
-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.
-+7%
++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.
-+206%
-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.
--1%
+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.
-+215%
-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 — 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
-
+
diff --git a/doc/modules/ROOT/images/bench/linux-socket_throughput-uring-g3.svg b/doc/modules/ROOT/images/bench/linux-socket_throughput-uring-g3.svg
index a1dae0e68..1078f32ea 100644
--- a/doc/modules/ROOT/images/bench/linux-socket_throughput-uring-g3.svg
+++ b/doc/modules/ROOT/images/bench/linux-socket_throughput-uring-g3.svg
@@ -8,53 +8,53 @@
asio (coroutines)
--20%
+-25%
-+20%
++25%
-+40%
++50%
-+60%
++75%
0%
-unidirectional/1024 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes.
-+51%
-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.
++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 — 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 — 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 — 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 — 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 — 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.
--2%
+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.
--5%
-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.
+-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 — 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.
-+2%
+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 — 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 — 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
diff --git a/doc/modules/ROOT/images/bench/linux-summary-epoll.svg b/doc/modules/ROOT/images/bench/linux-summary-epoll.svg
index 88bc3ba40..b1eac0def 100644
--- a/doc/modules/ROOT/images/bench/linux-summary-epoll.svg
+++ b/doc/modules/ROOT/images/bench/linux-summary-epoll.svg
@@ -5,47 +5,51 @@
← slower · within noise · faster → per benchmark, vs Boost.Asio (callbacks)
local_socket_latency
-3 benchmarks slower than asio (callbacks)
-3
-3 benchmarks within noise than asio (callbacks)
+4 benchmarks slower than asio (callbacks)
+4
+3 benchmarks within noise than asio (callbacks)
3
-6 benchmarks faster than asio (callbacks)
-6
-+11.1%
+5 benchmarks faster than asio (callbacks)
+5
++10.3%
socket_latency
-1 benchmark slower than asio (callbacks)
-3 benchmarks within noise than asio (callbacks)
-3
-8 benchmarks faster than asio (callbacks)
-8
-+5.8%
+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
-3 benchmarks slower than asio (callbacks)
-3
-11 benchmarks within noise than asio (callbacks)
-11
-13 benchmarks faster than asio (callbacks)
-13
-+2.4%
+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
-14 benchmarks within noise than asio (callbacks)
-14
-6 benchmarks faster than asio (callbacks)
-6
--0.8%
-http_server
-10 benchmarks slower than asio (callbacks)
-10
-1 benchmark within noise than asio (callbacks)
--6.0%
-fan_out
-18 benchmarks slower than asio (callbacks)
-18
--8.5%
-accept_churn
-9 benchmarks slower than asio (callbacks)
-9
--9.3%
+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%
diff --git a/doc/modules/ROOT/images/bench/linux-summary-uring.svg b/doc/modules/ROOT/images/bench/linux-summary-uring.svg
index 4c7ed13a7..fc9bae7e2 100644
--- a/doc/modules/ROOT/images/bench/linux-summary-uring.svg
+++ b/doc/modules/ROOT/images/bench/linux-summary-uring.svg
@@ -5,52 +5,42 @@
← slower · within noise · faster → per benchmark, vs Boost.Asio (callbacks)
local_socket_latency
-3 benchmarks slower than asio (callbacks)
-3
-1 benchmark within noise than asio (callbacks)
-8 benchmarks faster than asio (callbacks)
-8
-+20.3%
+12 benchmarks faster than asio (callbacks)
+12
++28.4%
socket_latency
-2 benchmarks slower than asio (callbacks)
-2
-2 benchmarks within noise than asio (callbacks)
-2
-8 benchmarks faster than asio (callbacks)
-8
-+10.7%
+1 benchmark within noise than asio (callbacks)
+11 benchmarks faster than asio (callbacks)
+11
++15.9%
socket_throughput
-3 benchmarks slower than asio (callbacks)
-3
-8 benchmarks within noise than asio (callbacks)
-8
-16 benchmarks faster than asio (callbacks)
-16
-+5.1%
+9 benchmarks within noise than asio (callbacks)
+9
+18 benchmarks faster than asio (callbacks)
+18
++8.9%
http_server
-4 benchmarks slower than asio (callbacks)
-4
-2 benchmarks within noise than asio (callbacks)
-2
-5 benchmarks faster than asio (callbacks)
-5
-+1.8%
-local_socket_throughput
-7 benchmarks slower than asio (callbacks)
-7
-10 benchmarks within noise than asio (callbacks)
-10
-7 benchmarks faster than asio (callbacks)
-7
--4.1%
-fan_out
-16 benchmarks slower than asio (callbacks)
-16
-2 benchmarks within noise than asio (callbacks)
-2
--10.1%
-accept_churn
-9 benchmarks slower than asio (callbacks)
-9
--26.1%
+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%
diff --git a/doc/modules/ROOT/images/bench/macos-accept_churn.svg b/doc/modules/ROOT/images/bench/macos-accept_churn.svg
index d4b1b786b..f58097b4e 100644
--- a/doc/modules/ROOT/images/bench/macos-accept_churn.svg
+++ b/doc/modules/ROOT/images/bench/macos-accept_churn.svg
@@ -9,43 +9,45 @@
asio (coroutines)
-60%
-
--40%
-
--20%
+
+-40%
+
+-20%
+
++20%
-+20%
-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.
++40%
+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.
--41%
+burst/100 — N connects are fired at once, then all N are accepted before closing; N is the burst size.
+-23%
+burst/100 — N connects are fired at once, then all N are accepted before closing; N is the burst size.
+-39%
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 — 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.
--28%
-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 — 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 — 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.
--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.
++0%
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 — 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.
-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 — Single connect/accept/close loop with a one-way one-byte transfer (client writes, server reads) per connection, one connection at a time.
+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.
-+10%
-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.
++16%
+sequential_lockless — Same as sequential, with the context in single-threaded lockless mode.
sequential_lockless
-
+
diff --git a/doc/modules/ROOT/images/bench/macos-fan_out-g1.svg b/doc/modules/ROOT/images/bench/macos-fan_out-g1.svg
index 4a9ea2fa1..c90b202c5 100644
--- a/doc/modules/ROOT/images/bench/macos-fan_out-g1.svg
+++ b/doc/modules/ROOT/images/bench/macos-fan_out-g1.svg
@@ -8,41 +8,43 @@
asio (coroutines)
--40%
-
--20%
+-50%
+
+-25%
+
++25%
-+20%
-0%
-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 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
--11%
++50%
+0%
+concurrent_parents/1 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
++0%
+concurrent_parents/1 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
+-10%
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.
--30%
+concurrent_parents/16 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
+-32%
+concurrent_parents/16 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
+-3%
concurrent_parents/16
-concurrent_parents/4 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
--8%
-concurrent_parents/4 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
--5%
+concurrent_parents/4 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
+-8%
+concurrent_parents/4 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
+-5%
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.
--5%
-concurrent_parents_lockless/1 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
--11%
+concurrent_parents_lockless/1 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
+0%
+concurrent_parents_lockless/1 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
+-10%
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.
--10%
-concurrent_parents_lockless/16 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
--31%
+concurrent_parents_lockless/16 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
+-6%
+concurrent_parents_lockless/16 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
++37%
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.
--11%
-concurrent_parents_lockless/4 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
--4%
+concurrent_parents_lockless/4 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
+-8%
+concurrent_parents_lockless/4 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
+-4%
concurrent_parents_lockless/4
-
+
diff --git a/doc/modules/ROOT/images/bench/macos-fan_out-g2.svg b/doc/modules/ROOT/images/bench/macos-fan_out-g2.svg
index c6a36f8fd..7627fdb97 100644
--- a/doc/modules/ROOT/images/bench/macos-fan_out-g2.svg
+++ b/doc/modules/ROOT/images/bench/macos-fan_out-g2.svg
@@ -18,45 +18,45 @@
+20%
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.
+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.
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.
--4%
-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 — 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 — One parent starts N sub-requests to echo servers and waits for all to finish before repeating; N is the fan-out width.
++1%
+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.
--7%
+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.
+-5%
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.
--27%
-fork_join_lockless/1 — Same as fork_join, with the context in single-threaded lockless mode; N is the fan-out width.
--53%
+fork_join_lockless/1 — Same as fork_join, with the context in single-threaded lockless mode; N is the fan-out width.
+-22%
+fork_join_lockless/1 — Same as fork_join, with the context in single-threaded lockless mode; N is the fan-out width.
+-54%
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 — 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 — 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.
+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 — 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 — 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 — 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 — 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
diff --git a/doc/modules/ROOT/images/bench/macos-http_server.svg b/doc/modules/ROOT/images/bench/macos-http_server.svg
index 056edc7eb..91ec71ff1 100644
--- a/doc/modules/ROOT/images/bench/macos-http_server.svg
+++ b/doc/modules/ROOT/images/bench/macos-http_server.svg
@@ -9,47 +9,49 @@
asio (coroutines)
-40%
-
--20%
+
+-20%
+
++20%
-+20%
-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.
++40%
+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.
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.
-0%
+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.
+0%
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 — 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 — 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 — 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.
+multithread/16 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count.
++16%
+multithread/16 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count.
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.
+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.
multithread/2
-multithread/4 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count.
-+12%
-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 — 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 — 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.
--6%
+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.
+-6%
single_conn
-single_conn_lockless — Same as single_conn, with the context in single-threaded lockless mode.
--21%
-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.
+-21%
+single_conn_lockless — Same as single_conn, with the context in single-threaded lockless mode.
single_conn_lockless
-
+
diff --git a/doc/modules/ROOT/images/bench/macos-local_socket_latency.svg b/doc/modules/ROOT/images/bench/macos-local_socket_latency.svg
index 4f284e0b6..6f85c3bd8 100644
--- a/doc/modules/ROOT/images/bench/macos-local_socket_latency.svg
+++ b/doc/modules/ROOT/images/bench/macos-local_socket_latency.svg
@@ -16,44 +16,44 @@
+150%
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 — 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 — 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 — 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.
++0%
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 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs.
-+0%
concurrent_lockless/1
-concurrent_lockless/16 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs.
-+59%
-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.
++63%
+concurrent_lockless/16 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs.
+-6%
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 — 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 — 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 — 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 — 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.
-+96%
+pingpong_lockless/1 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes.
++96%
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 — 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 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes.
pingpong_lockless/64
diff --git a/doc/modules/ROOT/images/bench/macos-local_socket_throughput-g1.svg b/doc/modules/ROOT/images/bench/macos-local_socket_throughput-g1.svg
index c14652bb1..6f4169219 100644
--- a/doc/modules/ROOT/images/bench/macos-local_socket_throughput-g1.svg
+++ b/doc/modules/ROOT/images/bench/macos-local_socket_throughput-g1.svg
@@ -18,45 +18,45 @@
+1000%
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.
bidirectional/1024 — Both ends of the socket pair write and read simultaneously; N is the chunk size in bytes.
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 — 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 — 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 — 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.
+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.
+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.
-+709%
+bidirectional_lockless/1024 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes.
++757%
bidirectional_lockless/1024 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes.
0%
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 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes.
--3%
bidirectional_lockless/1048576
-bidirectional_lockless/16384 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes.
-+241%
+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 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes.
++245%
+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 — 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 — 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
diff --git a/doc/modules/ROOT/images/bench/macos-local_socket_throughput-g2.svg b/doc/modules/ROOT/images/bench/macos-local_socket_throughput-g2.svg
index 9f8affb57..f0eb158e5 100644
--- a/doc/modules/ROOT/images/bench/macos-local_socket_throughput-g2.svg
+++ b/doc/modules/ROOT/images/bench/macos-local_socket_throughput-g2.svg
@@ -18,45 +18,45 @@
+2000%
0%
-unidirectional/1024 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes.
-+1402%
-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.
++1454%
+unidirectional/1024 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes.
+-7%
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 — 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 — 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.
++482%
unidirectional/262144 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes.
-0%
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 — 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.
-+466%
+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.
--7%
+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 — 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 — 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 — 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 — 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 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes.
+0%
unidirectional_lockless/65536
diff --git a/doc/modules/ROOT/images/bench/macos-socket_latency.svg b/doc/modules/ROOT/images/bench/macos-socket_latency.svg
index e8137047e..b9f4ad5e5 100644
--- a/doc/modules/ROOT/images/bench/macos-socket_latency.svg
+++ b/doc/modules/ROOT/images/bench/macos-socket_latency.svg
@@ -14,45 +14,45 @@
+100%
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 — 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 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs.
++3%
+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 — 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.
+-9%
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 — 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.
-+8%
-concurrent_lockless/16 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs.
+concurrent_lockless/16 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs.
+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 — 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 — 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.
-+5%
+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 — 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.
-+70%
-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 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes.
++71%
+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 — 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 — 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.
++4%
pingpong_lockless/64
diff --git a/doc/modules/ROOT/images/bench/macos-socket_throughput-g1.svg b/doc/modules/ROOT/images/bench/macos-socket_throughput-g1.svg
index bd16d73ea..18e50e83f 100644
--- a/doc/modules/ROOT/images/bench/macos-socket_throughput-g1.svg
+++ b/doc/modules/ROOT/images/bench/macos-socket_throughput-g1.svg
@@ -8,53 +8,51 @@
asio (coroutines)
--50%
-
-+50%
-
-+100%
+-100%
+
++100%
-+150%
-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.
++200%
+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.
--12%
-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 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes.
++3%
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 — 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 — 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 — 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 — 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.
-+104%
-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.
++136%
+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 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes.
+-12%
+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 — 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.
--20%
+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.
+-19%
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 — 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.
-0%
+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
-
+
diff --git a/doc/modules/ROOT/images/bench/macos-socket_throughput-g2.svg b/doc/modules/ROOT/images/bench/macos-socket_throughput-g2.svg
index b62069b9c..056cf72dc 100644
--- a/doc/modules/ROOT/images/bench/macos-socket_throughput-g2.svg
+++ b/doc/modules/ROOT/images/bench/macos-socket_throughput-g2.svg
@@ -14,20 +14,20 @@
+10%
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.
-+2%
-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.
-+2%
+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 — 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/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.
-+1%
-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.
-+5%
+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.
++1%
+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.
--11%
-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 — 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/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
diff --git a/doc/modules/ROOT/images/bench/macos-socket_throughput-g3.svg b/doc/modules/ROOT/images/bench/macos-socket_throughput-g3.svg
index d572b230e..212b4a24b 100644
--- a/doc/modules/ROOT/images/bench/macos-socket_throughput-g3.svg
+++ b/doc/modules/ROOT/images/bench/macos-socket_throughput-g3.svg
@@ -8,53 +8,53 @@
asio (coroutines)
--50%
+-100%
-+50%
++100%
-+100%
++200%
-+150%
++300%
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 — 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.
-0%
-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 — 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 — 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.
--23%
+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.
+-23%
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 — 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 — 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.
-+125%
-unidirectional_lockless/1024 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes.
-+10%
+unidirectional_lockless/1024 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes.
++241%
+unidirectional_lockless/1024 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes.
++7%
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 — 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 — 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 — 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 — 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 — 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
diff --git a/doc/modules/ROOT/images/bench/macos-summary.svg b/doc/modules/ROOT/images/bench/macos-summary.svg
index 81fe7912f..84e811671 100644
--- a/doc/modules/ROOT/images/bench/macos-summary.svg
+++ b/doc/modules/ROOT/images/bench/macos-summary.svg
@@ -7,41 +7,41 @@
local_socket_throughput
24 benchmarks faster than asio (callbacks)
24
-+467.2%
++481.9%
local_socket_latency
12 benchmarks faster than asio (callbacks)
12
-+95.7%
-socket_latency
-2 benchmarks within noise than asio (callbacks)
-10 benchmarks faster than asio (callbacks)
-10
-+66.3%
-socket_throughput
-3 benchmarks slower than asio (callbacks)
-3
-7 benchmarks within noise than asio (callbacks)
-7
-17 benchmarks faster than asio (callbacks)
-17
-+63.3%
++96.1%
+socket_throughput
+2 benchmarks slower than asio (callbacks)
+8 benchmarks within noise than asio (callbacks)
+8
+17 benchmarks faster than asio (callbacks)
+17
++69.4%
+socket_latency
+2 benchmarks within noise than asio (callbacks)
+10 benchmarks faster than asio (callbacks)
+10
++65.1%
http_server
-6 benchmarks slower than asio (callbacks)
-6
-3 benchmarks within noise than asio (callbacks)
-3
-2 benchmarks faster than asio (callbacks)
--4.5%
-fan_out
-16 benchmarks slower than asio (callbacks)
-16
-2 benchmarks within noise than asio (callbacks)
--8.7%
-accept_churn
-5 benchmarks slower than asio (callbacks)
-5
-1 benchmark within noise than asio (callbacks)
-3 benchmarks faster than asio (callbacks)
-3
--10.2%
+6 benchmarks slower than asio (callbacks)
+6
+1 benchmark within noise than asio (callbacks)
+4 benchmarks faster than asio (callbacks)
+4
+-2.5%
+accept_churn
+1 benchmark slower than asio (callbacks)
+5 benchmarks within noise than asio (callbacks)
+5
+3 benchmarks faster than asio (callbacks)
+3
+-4.1%
+fan_out
+8 benchmarks slower than asio (callbacks)
+8
+10 benchmarks within noise than asio (callbacks)
+10
+-7.0%
diff --git a/doc/modules/ROOT/images/bench/windows-accept_churn.svg b/doc/modules/ROOT/images/bench/windows-accept_churn.svg
index bd8ed3a41..8e9b08565 100644
--- a/doc/modules/ROOT/images/bench/windows-accept_churn.svg
+++ b/doc/modules/ROOT/images/bench/windows-accept_churn.svg
@@ -8,42 +8,46 @@
asio (coroutines)
--20%
-
--10%
+-15%
+
+-10%
+
+-5%
+
++5%
+10%
-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.
+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.
+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 — 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.
--8%
-burst_lockless/100 — Same as burst, with the context in single-threaded lockless mode; N is the burst size.
-+6%
+burst_lockless/100 — Same as burst, with the context in single-threaded lockless mode; N is the burst size.
+-4%
+burst_lockless/100 — Same as burst, with the context in single-threaded lockless mode; N is the burst size.
++5%
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.
--10%
-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.
+-9%
+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.
+-4%
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 — 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.
-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 — 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.
-sequential — Single connect/accept/close loop with a one-way one-byte transfer (client writes, server reads) per connection, one connection at a time.
--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.
+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 — 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
-
+
diff --git a/doc/modules/ROOT/images/bench/windows-fan_out-g1.svg b/doc/modules/ROOT/images/bench/windows-fan_out-g1.svg
index a6d4266ed..aef79c220 100644
--- a/doc/modules/ROOT/images/bench/windows-fan_out-g1.svg
+++ b/doc/modules/ROOT/images/bench/windows-fan_out-g1.svg
@@ -16,35 +16,35 @@
+5%
0%
-concurrent_parents/1 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
--7%
-concurrent_parents/1 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
--11%
+concurrent_parents/1 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
+-8%
+concurrent_parents/1 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
+-11%
concurrent_parents/1
-concurrent_parents/16 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
--11%
-concurrent_parents/16 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
--11%
+concurrent_parents/16 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
+-12%
+concurrent_parents/16 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
+-12%
concurrent_parents/16
-concurrent_parents/4 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
--9%
-concurrent_parents/4 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
--10%
+concurrent_parents/4 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
+-10%
+concurrent_parents/4 — N independent parents each fan out to 16 sub-requests at once; N is the number of parents.
+-10%
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.
--7%
-concurrent_parents_lockless/1 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
--10%
+concurrent_parents_lockless/1 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
+-8%
+concurrent_parents_lockless/1 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
+-9%
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.
--11%
-concurrent_parents_lockless/16 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
--11%
+concurrent_parents_lockless/16 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
+-12%
+concurrent_parents_lockless/16 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
+-10%
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.
--9%
-concurrent_parents_lockless/4 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
--11%
+concurrent_parents_lockless/4 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
+-10%
+concurrent_parents_lockless/4 — Same as concurrent_parents, with the context in single-threaded lockless mode; N is the number of parents.
+-10%
concurrent_parents_lockless/4
diff --git a/doc/modules/ROOT/images/bench/windows-fan_out-g2.svg b/doc/modules/ROOT/images/bench/windows-fan_out-g2.svg
index aa31ed37c..7986f032a 100644
--- a/doc/modules/ROOT/images/bench/windows-fan_out-g2.svg
+++ b/doc/modules/ROOT/images/bench/windows-fan_out-g2.svg
@@ -18,45 +18,45 @@
+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.
+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.
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 — 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.
--5%
-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.
+-6%
+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.
+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.
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 — 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 — 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.
--10%
+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.
+-9%
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 — 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 — 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.
+-12%
+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 — 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.
--11%
-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 — 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.
--13%
+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.
+-14%
nested_lockless/4
diff --git a/doc/modules/ROOT/images/bench/windows-http_server.svg b/doc/modules/ROOT/images/bench/windows-http_server.svg
index ed95e61ce..13c8e56b9 100644
--- a/doc/modules/ROOT/images/bench/windows-http_server.svg
+++ b/doc/modules/ROOT/images/bench/windows-http_server.svg
@@ -8,50 +8,52 @@
asio (coroutines)
--7.5%
-
--5%
-
--2.5%
+-10%
+
+-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.
+0%
+concurrent/1 — N client/server pairs run the single_conn request/response loop concurrently; N is the number of connections.
+-2%
+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 — 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 — 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 — 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 — 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.
--6%
-multithread/16 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count.
--2%
+multithread/16 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count.
+-7%
+multithread/16 — 32 client/server pairs share one context serviced by N threads running the context; N is the thread count.
+-2%
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.
+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.
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 — 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 — 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 — 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.
-0%
-single_conn_lockless — Same as single_conn, with the context in single-threaded lockless mode.
--5%
+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.
+-4%
single_conn_lockless
-
+
diff --git a/doc/modules/ROOT/images/bench/windows-socket_latency.svg b/doc/modules/ROOT/images/bench/windows-socket_latency.svg
index 14f90cc03..5932a1c3f 100644
--- a/doc/modules/ROOT/images/bench/windows-socket_latency.svg
+++ b/doc/modules/ROOT/images/bench/windows-socket_latency.svg
@@ -8,53 +8,55 @@
asio (coroutines)
--15%
-
--10%
-
--5%
+-20%
+
+-15%
+
+-10%
+
+-5%
+5%
-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.
+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.
--11%
-concurrent/16 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs.
--8%
+concurrent/16 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs.
+-14%
+concurrent/16 — N independent 64-byte pingpong pairs run concurrently on one context; N is the number of connection pairs.
+-13%
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 — 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 — 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.
+-5%
concurrent_lockless/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 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs.
+concurrent_lockless/16 — Same as concurrent, with the context in single-threaded lockless mode; N is the number of connection pairs.
+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 — 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.
--6%
+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 — One TCP connection ping-pongs a message client->server->client; N is the message size in bytes.
+-9%
+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 — 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 — 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 — 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.
--7%
-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 — Same as pingpong, with the context in single-threaded lockless mode; N is the message size in bytes.
pingpong_lockless/64
-
+
diff --git a/doc/modules/ROOT/images/bench/windows-socket_throughput-g1.svg b/doc/modules/ROOT/images/bench/windows-socket_throughput-g1.svg
index 42c5b9e02..19eb6f8e8 100644
--- a/doc/modules/ROOT/images/bench/windows-socket_throughput-g1.svg
+++ b/doc/modules/ROOT/images/bench/windows-socket_throughput-g1.svg
@@ -8,53 +8,53 @@
asio (coroutines)
--15%
+-7.5%
--10%
+-5%
--5%
+-2.5%
-+5%
++2.5%
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.
--5%
+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.
--9%
-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 — Both ends of the connection write and read simultaneously; N is the chunk size in bytes.
++1%
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 — 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.
-+0%
-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.
++0%
+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 — 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 — 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.
+-6%
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 — Same as bidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes.
+-4%
+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 — 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 — 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.
--1%
+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 — 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 — 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
diff --git a/doc/modules/ROOT/images/bench/windows-socket_throughput-g2.svg b/doc/modules/ROOT/images/bench/windows-socket_throughput-g2.svg
index 9c012f2ce..6671aec18 100644
--- a/doc/modules/ROOT/images/bench/windows-socket_throughput-g2.svg
+++ b/doc/modules/ROOT/images/bench/windows-socket_throughput-g2.svg
@@ -14,20 +14,20 @@
+2%
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.
--2%
-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.
--2%
+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.
+-2%
+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.
+-2%
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.
--3%
-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.
--3%
+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.
+-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.
+-2%
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.
-0%
-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 — 32 bidirectional connection pairs share one context serviced by N threads running the context, with 64 KiB chunks; N is the thread count.
+-2%
+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
diff --git a/doc/modules/ROOT/images/bench/windows-socket_throughput-g3.svg b/doc/modules/ROOT/images/bench/windows-socket_throughput-g3.svg
index 1d9566a1b..d433740fe 100644
--- a/doc/modules/ROOT/images/bench/windows-socket_throughput-g3.svg
+++ b/doc/modules/ROOT/images/bench/windows-socket_throughput-g3.svg
@@ -8,55 +8,53 @@
asio (coroutines)
--6%
-
--4%
-
--2%
-
-+2%
+-10%
+
+-5%
+
++5%
-+4%
-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.
++10%
+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.
-+1%
+unidirectional/1048576 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes.
++1%
+unidirectional/1048576 — One writer streams to one reader as fast as possible; N is the write/read chunk size in bytes.
++5%
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 — 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 — 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 — 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 — 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 — 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.
-+2%
-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.
+-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.
--3%
-unidirectional_lockless/16384 — Same as unidirectional, with the context in single-threaded lockless mode; N is the chunk size in bytes.
--4%
+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 — 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 — 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 — 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.
+-5%
unidirectional_lockless/65536
-
+
diff --git a/doc/modules/ROOT/images/bench/windows-summary.svg b/doc/modules/ROOT/images/bench/windows-summary.svg
index ac6fb317d..0166d579b 100644
--- a/doc/modules/ROOT/images/bench/windows-summary.svg
+++ b/doc/modules/ROOT/images/bench/windows-summary.svg
@@ -4,29 +4,26 @@
← slower · within noise · faster → per benchmark, vs Boost.Asio (callbacks)
-http_server
-8 benchmarks slower than asio (callbacks)
-8
-3 benchmarks within noise than asio (callbacks)
-3
--1.7%
-socket_throughput
-13 benchmarks slower than asio (callbacks)
-13
-14 benchmarks within noise than asio (callbacks)
-14
--2.1%
-socket_latency
-11 benchmarks slower than asio (callbacks)
-11
-1 benchmark within noise than asio (callbacks)
--7.3%
-accept_churn
-9 benchmarks slower than asio (callbacks)
-9
--8.5%
+socket_throughput
+13 benchmarks slower than asio (callbacks)
+13
+14 benchmarks within noise than asio (callbacks)
+14
+-3.1%
+http_server
+11 benchmarks slower than asio (callbacks)
+11
+-3.4%
+accept_churn
+9 benchmarks slower than asio (callbacks)
+9
+-6.9%
+socket_latency
+12 benchmarks slower than asio (callbacks)
+12
+-9.8%
fan_out
18 benchmarks slower than asio (callbacks)
18
--8.8%
+-10.0%
diff --git a/doc/modules/ROOT/pages/benchmarks/index.adoc b/doc/modules/ROOT/pages/benchmarks/index.adoc
index 728bbcac5..42cc8ffe3 100644
--- a/doc/modules/ROOT/pages/benchmarks/index.adoc
+++ b/doc/modules/ROOT/pages/benchmarks/index.adoc
@@ -3,7 +3,7 @@
:page-mode: explanation
:toc: left
-_Generated 2026-10-02 from corosio `e2de06fda069` — https://github.com/cppalliance/corosio/actions/runs/37015995763[benchmark run]. This page is fully generated; do not edit by hand (see <>)._
+_Generated 2026-11-06 from corosio `0b3830d5c30b` — https://github.com/cppalliance/corosio/actions/runs/42119198783[benchmark run]. This page is fully generated; do not edit by hand (see <>)._
This report compares Boost.Corosio against Boost.Asio using coroutines (the `asio` configuration) and Boost.Asio using callback-based handlers (`asio_callback`) across the corosio benchmark suite. Its purpose is to track corosio's performance relative to an established async I/O library as both evolve, not to crown a universal winner.
@@ -31,7 +31,7 @@ python3 .github/bench/report_page.py --input-dir \
--output-dir doc/modules/ROOT
----
-Source data: https://github.com/cppalliance/corosio/actions/runs/37015995763[workflow run]. Regenerate this page with the command above. GitHub retains the run's raw JSON artifacts for 90 days; these pages are the durable record.
+Source data: https://github.com/cppalliance/corosio/actions/runs/42119198783[workflow run]. Regenerate this page with the command above. GitHub retains the run's raw JSON artifacts for 90 days; these pages are the durable record.
== Platforms
diff --git a/doc/modules/ROOT/pages/benchmarks/linux.adoc b/doc/modules/ROOT/pages/benchmarks/linux.adoc
index 14fd563ea..5ed344e8e 100644
--- a/doc/modules/ROOT/pages/benchmarks/linux.adoc
+++ b/doc/modules/ROOT/pages/benchmarks/linux.adoc
@@ -2,7 +2,7 @@
:page-mode: explanation
:toc: left
-_Generated 2026-10-02 from corosio `e2de06fda069` — https://github.com/cppalliance/corosio/actions/runs/37015995763[benchmark run]. This page is fully generated; do not edit by hand (see the xref:benchmarks/index.adoc[Benchmarks landing page])._
+_Generated 2026-11-06 from corosio `0b3830d5c30b` — https://github.com/cppalliance/corosio/actions/runs/42119198783[benchmark run]. This page is fully generated; do not edit by hand (see the xref:benchmarks/index.adoc[Benchmarks landing page])._
== Summary
@@ -10,13 +10,13 @@ _Within noise_ means the relative difference is within twice the combined run-to
=== io_uring
-**44 faster · 25 within noise · 44 slower** of 113 benchmarks — median **-0.7%** vs Boost.Asio (callbacks) on the same reactor.
+**58 faster · 48 within noise · 7 slower** of 113 benchmarks — median **+2.9%** vs Boost.Asio (callbacks) on the same reactor.
image::bench/linux-summary-uring.svg[summary,role=bch-block,opts=inline]
=== epoll
-**33 faster · 32 within noise · 48 slower** of 113 benchmarks — median **-2.4%** vs Boost.Asio (callbacks) on the same reactor.
+**31 faster · 35 within noise · 47 slower** of 113 benchmarks — median **-1.0%** vs Boost.Asio (callbacks) on the same reactor.
image::bench/linux-summary-epoll.svg[summary,role=bch-block,opts=inline]
@@ -32,13 +32,13 @@ image::bench/linux-summary-epoll.svg[summary,role=bch-block,opts=inline]
| Compiler | c++ (Ubuntu 15.2.0-16ubuntu1) 15.2.0
| CMake | `cmake version 4.2.3`
| liburing | 2.14-1
-| Boost commit | 39fa1e9a3491bd099b570935b3f3422065f91b03
-| Asio commit | a7dc25b4cb6c49a6946d86ea20664f1027203225
+| Boost commit | b6d874b77b75085a1b35c640a76d37ab8cd9bb97
+| Asio commit | e99d9da6d9b76a222e29dcaf3d2df51c788b7527
| Asio reactor | epoll and io_uring (matched per configuration)
-| Capy commit | a372a6b054261f29497ac0d19c2a9533f9eaad40
-| Corosio commit | e2de06fda069607f34bc957cbefcbd9ba12fddca
-| Corosio branch | pr/benchmark-report
-| Date (UTC) | 2026-10-02
+| Capy commit | bdadc6adef8c8eb79da6454373175bb1428be524
+| Corosio commit | 0b3830d5c30b96e4a95c0248953575ba7ffcd4d1
+| Corosio branch | develop
+| Date (UTC) | 2026-11-06
| Iterations | 7
| Duration per benchmark (s) | 2.0
|===
@@ -61,33 +61,33 @@ image::bench/linux-accept_churn-uring.svg[accept churn comparison (io_uring),rol
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `burst/10` | corosio (io_uring) | 1.70K ops/s | 1.19% | -29.3%
-| `burst/10` | asio (coroutines, io_uring) | 2.38K ops/s | 0.97% | -1.0%
-| `burst/10` | asio (callbacks, io_uring) | 2.40K ops/s | 1.23% | baseline (io_uring)
-| `burst/100` | corosio (io_uring) | 173.5 ops/s | 1.03% | -29.2%
-| `burst/100` | asio (coroutines, io_uring) | 245.5 ops/s | 0.95% | +0.2%
-| `burst/100` | asio (callbacks, io_uring) | 244.9 ops/s | 0.78% | baseline (io_uring)
-| `burst_lockless/10` | corosio (io_uring) | 1.81K ops/s | 1.38% | -25.0%
-| `burst_lockless/10` | asio (coroutines, io_uring) | 2.39K ops/s | 1.12% | -1.0%
-| `burst_lockless/10` | asio (callbacks, io_uring) | 2.42K ops/s | 1.20% | baseline (io_uring)
-| `burst_lockless/100` | corosio (io_uring) | 185.0 ops/s | 1.10% | -25.1%
-| `burst_lockless/100` | asio (coroutines, io_uring) | 248.0 ops/s | 0.88% | +0.4%
-| `burst_lockless/100` | asio (callbacks, io_uring) | 246.9 ops/s | 0.70% | baseline (io_uring)
-| `concurrent/1` | corosio (io_uring) | 12.66K ops/s | 1.30% | -26.1%
-| `concurrent/1` | asio (coroutines, io_uring) | 16.65K ops/s | 0.90% | -2.8%
-| `concurrent/1` | asio (callbacks, io_uring) | 17.13K ops/s | 0.93% | baseline (io_uring)
-| `concurrent/16` | corosio (io_uring) | 12.44K ops/s | 1.00% | -35.3%
-| `concurrent/16` | asio (coroutines, io_uring) | 18.96K ops/s | 0.89% | -1.4%
-| `concurrent/16` | asio (callbacks, io_uring) | 19.22K ops/s | 0.96% | baseline (io_uring)
-| `concurrent/4` | corosio (io_uring) | 12.54K ops/s | 1.01% | -31.8%
-| `concurrent/4` | asio (coroutines, io_uring) | 18.04K ops/s | 0.95% | -1.9%
-| `concurrent/4` | asio (callbacks, io_uring) | 18.39K ops/s | 0.93% | baseline (io_uring)
-| `sequential` | corosio (io_uring) | 12.68K ops/s | 1.32% | -25.7%
-| `sequential` | asio (coroutines, io_uring) | 16.73K ops/s | 0.55% | -2.0%
-| `sequential` | asio (callbacks, io_uring) | 17.07K ops/s | 0.88% | baseline (io_uring)
-| `sequential_lockless` | corosio (io_uring) | 13.52K ops/s | 1.24% | -21.7%
-| `sequential_lockless` | asio (coroutines, io_uring) | 16.86K ops/s | 0.91% | -2.4%
-| `sequential_lockless` | asio (callbacks, io_uring) | 17.27K ops/s | 0.87% | baseline (io_uring)
+| `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)
|===
====
@@ -105,33 +105,33 @@ image::bench/linux-accept_churn-epoll.svg[accept churn comparison (epoll),role=b
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `burst/10` | corosio (epoll) | 1.87K ops/s | 0.71% | -12.5%
-| `burst/10` | asio (coroutines, epoll) | 2.05K ops/s | 0.26% | -4.2%
-| `burst/10` | asio (callbacks, epoll) | 2.14K ops/s | 0.84% | baseline (epoll)
-| `burst/100` | corosio (epoll) | 188.4 ops/s | 0.85% | -12.8%
-| `burst/100` | asio (coroutines, epoll) | 208.7 ops/s | 0.26% | -3.3%
-| `burst/100` | asio (callbacks, epoll) | 215.9 ops/s | 0.24% | baseline (epoll)
-| `burst_lockless/10` | corosio (epoll) | 1.88K ops/s | 0.86% | -12.3%
-| `burst_lockless/10` | asio (coroutines, epoll) | 2.06K ops/s | 0.91% | -4.1%
-| `burst_lockless/10` | asio (callbacks, epoll) | 2.14K ops/s | 0.24% | baseline (epoll)
-| `burst_lockless/100` | corosio (epoll) | 189.9 ops/s | 0.78% | -12.3%
-| `burst_lockless/100` | asio (coroutines, epoll) | 209.8 ops/s | 0.89% | -3.1%
-| `burst_lockless/100` | asio (callbacks, epoll) | 216.5 ops/s | 0.49% | baseline (epoll)
-| `concurrent/1` | corosio (epoll) | 14.90K ops/s | 0.38% | -4.7%
-| `concurrent/1` | asio (coroutines, epoll) | 15.19K ops/s | 0.35% | -2.9%
-| `concurrent/1` | asio (callbacks, epoll) | 15.63K ops/s | 1.13% | baseline (epoll)
-| `concurrent/16` | corosio (epoll) | 14.91K ops/s | 0.45% | -9.3%
-| `concurrent/16` | asio (coroutines, epoll) | 16.12K ops/s | 0.28% | -1.9%
-| `concurrent/16` | asio (callbacks, epoll) | 16.43K ops/s | 0.97% | baseline (epoll)
-| `concurrent/4` | corosio (epoll) | 14.91K ops/s | 0.40% | -7.0%
-| `concurrent/4` | asio (coroutines, epoll) | 15.66K ops/s | 0.40% | -2.3%
-| `concurrent/4` | asio (callbacks, epoll) | 16.03K ops/s | 0.94% | baseline (epoll)
-| `sequential` | corosio (epoll) | 14.93K ops/s | 0.48% | -3.7%
-| `sequential` | asio (coroutines, epoll) | 15.20K ops/s | 0.98% | -2.0%
-| `sequential` | asio (callbacks, epoll) | 15.51K ops/s | 0.58% | baseline (epoll)
-| `sequential_lockless` | corosio (epoll) | 14.99K ops/s | 0.51% | -4.7%
-| `sequential_lockless` | asio (coroutines, epoll) | 15.34K ops/s | 0.86% | -2.4%
-| `sequential_lockless` | asio (callbacks, epoll) | 15.73K ops/s | 0.83% | baseline (epoll)
+| `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)
|===
====
@@ -157,24 +157,24 @@ image::bench/linux-fan_out-uring-g1.svg[fan out comparison (io_uring), part 1,ro
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `concurrent_parents/1` | corosio (io_uring) | 3.43K ops/s | 0.77% | -12.6%
-| `concurrent_parents/1` | asio (coroutines, io_uring) | 3.78K ops/s | 1.13% | -3.7%
-| `concurrent_parents/1` | asio (callbacks, io_uring) | 3.92K ops/s | 0.60% | baseline (io_uring)
-| `concurrent_parents/16` | corosio (io_uring) | 3.32K ops/s | 0.47% | -13.3%
-| `concurrent_parents/16` | asio (coroutines, io_uring) | 3.71K ops/s | 1.26% | -3.0%
-| `concurrent_parents/16` | asio (callbacks, io_uring) | 3.82K ops/s | 0.58% | baseline (io_uring)
-| `concurrent_parents/4` | corosio (io_uring) | 3.34K ops/s | 0.49% | -13.3%
-| `concurrent_parents/4` | asio (coroutines, io_uring) | 3.73K ops/s | 1.16% | -3.1%
-| `concurrent_parents/4` | asio (callbacks, io_uring) | 3.85K ops/s | 0.26% | baseline (io_uring)
-| `concurrent_parents_lockless/1` | corosio (io_uring) | 3.65K ops/s | 0.26% | -8.1%
-| `concurrent_parents_lockless/1` | asio (coroutines, io_uring) | 3.83K ops/s | 1.27% | -3.5%
-| `concurrent_parents_lockless/1` | asio (callbacks, io_uring) | 3.97K ops/s | 0.92% | baseline (io_uring)
-| `concurrent_parents_lockless/16` | corosio (io_uring) | 3.53K ops/s | 0.16% | -9.0%
-| `concurrent_parents_lockless/16` | asio (coroutines, io_uring) | 3.75K ops/s | 0.85% | -3.3%
-| `concurrent_parents_lockless/16` | asio (callbacks, io_uring) | 3.88K ops/s | 0.88% | baseline (io_uring)
-| `concurrent_parents_lockless/4` | corosio (io_uring) | 3.55K ops/s | 0.44% | -8.8%
-| `concurrent_parents_lockless/4` | asio (coroutines, io_uring) | 3.77K ops/s | 0.84% | -3.3%
-| `concurrent_parents_lockless/4` | asio (callbacks, io_uring) | 3.89K ops/s | 0.84% | baseline (io_uring)
+| `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)
|===
====
@@ -190,42 +190,42 @@ image::bench/linux-fan_out-uring-g2.svg[fan out comparison (io_uring), part 2,ro
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `fork_join/1` | corosio (io_uring) | 53.35K ops/s | 1.17% | -0.9%
-| `fork_join/1` | asio (coroutines, io_uring) | 47.61K ops/s | 1.20% | -11.6%
-| `fork_join/1` | asio (callbacks, io_uring) | 53.83K ops/s | 1.02% | baseline (io_uring)
-| `fork_join/16` | corosio (io_uring) | 3.44K ops/s | 0.97% | -12.3%
-| `fork_join/16` | asio (coroutines, io_uring) | 3.79K ops/s | 0.84% | -3.4%
-| `fork_join/16` | asio (callbacks, io_uring) | 3.92K ops/s | 1.20% | baseline (io_uring)
-| `fork_join/4` | corosio (io_uring) | 13.74K ops/s | 1.19% | -9.7%
-| `fork_join/4` | asio (coroutines, io_uring) | 14.39K ops/s | 0.91% | -5.3%
-| `fork_join/4` | asio (callbacks, io_uring) | 15.21K ops/s | 1.19% | baseline (io_uring)
-| `fork_join/64` | corosio (io_uring) | 813.2 ops/s | 1.01% | -15.2%
-| `fork_join/64` | asio (coroutines, io_uring) | 933.8 ops/s | 0.85% | -2.6%
-| `fork_join/64` | asio (callbacks, io_uring) | 958.5 ops/s | 0.88% | baseline (io_uring)
-| `fork_join_lockless/1` | corosio (io_uring) | 55.85K ops/s | 0.69% | +1.7%
-| `fork_join_lockless/1` | asio (coroutines, io_uring) | 48.68K ops/s | 1.11% | -11.3%
-| `fork_join_lockless/1` | asio (callbacks, io_uring) | 54.89K ops/s | 1.12% | baseline (io_uring)
-| `fork_join_lockless/16` | corosio (io_uring) | 3.66K ops/s | 0.83% | -7.9%
-| `fork_join_lockless/16` | asio (coroutines, io_uring) | 3.85K ops/s | 0.98% | -3.1%
-| `fork_join_lockless/16` | asio (callbacks, io_uring) | 3.97K ops/s | 0.92% | baseline (io_uring)
-| `fork_join_lockless/4` | corosio (io_uring) | 14.55K ops/s | 0.19% | -5.7%
-| `fork_join_lockless/4` | asio (coroutines, io_uring) | 14.57K ops/s | 1.27% | -5.6%
-| `fork_join_lockless/4` | asio (callbacks, io_uring) | 15.43K ops/s | 1.08% | baseline (io_uring)
-| `fork_join_lockless/64` | corosio (io_uring) | 867.2 ops/s | 0.73% | -10.5%
-| `fork_join_lockless/64` | asio (coroutines, io_uring) | 946.7 ops/s | 1.21% | -2.3%
-| `fork_join_lockless/64` | asio (callbacks, io_uring) | 969.4 ops/s | 0.83% | baseline (io_uring)
-| `nested/16` | corosio (io_uring) | 804.1 ops/s | 1.20% | -16.1%
-| `nested/16` | asio (coroutines, io_uring) | 924.9 ops/s | 0.94% | -3.5%
-| `nested/16` | asio (callbacks, io_uring) | 958.0 ops/s | 0.59% | baseline (io_uring)
-| `nested/4` | corosio (io_uring) | 3.40K ops/s | 1.16% | -13.3%
-| `nested/4` | asio (coroutines, io_uring) | 3.77K ops/s | 1.08% | -3.7%
-| `nested/4` | asio (callbacks, io_uring) | 3.92K ops/s | 0.90% | baseline (io_uring)
-| `nested_lockless/16` | corosio (io_uring) | 856.8 ops/s | 0.83% | -11.7%
-| `nested_lockless/16` | asio (coroutines, io_uring) | 935.0 ops/s | 1.11% | -3.7%
-| `nested_lockless/16` | asio (callbacks, io_uring) | 970.5 ops/s | 0.62% | baseline (io_uring)
-| `nested_lockless/4` | corosio (io_uring) | 3.63K ops/s | 1.08% | -8.7%
-| `nested_lockless/4` | asio (coroutines, io_uring) | 3.81K ops/s | 1.04% | -4.1%
-| `nested_lockless/4` | asio (callbacks, io_uring) | 3.97K ops/s | 0.65% | baseline (io_uring)
+| `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)
|===
====
@@ -243,24 +243,24 @@ image::bench/linux-fan_out-epoll-g1.svg[fan out comparison (epoll), part 1,role=
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `concurrent_parents/1` | corosio (epoll) | 3.69K ops/s | 0.10% | -8.3%
-| `concurrent_parents/1` | asio (coroutines, epoll) | 3.83K ops/s | 1.00% | -4.8%
-| `concurrent_parents/1` | asio (callbacks, epoll) | 4.02K ops/s | 0.45% | baseline (epoll)
-| `concurrent_parents/16` | corosio (epoll) | 3.59K ops/s | 0.10% | -8.8%
-| `concurrent_parents/16` | asio (coroutines, epoll) | 3.74K ops/s | 0.81% | -4.9%
-| `concurrent_parents/16` | asio (callbacks, epoll) | 3.93K ops/s | 0.77% | baseline (epoll)
-| `concurrent_parents/4` | corosio (epoll) | 3.60K ops/s | 0.12% | -8.6%
-| `concurrent_parents/4` | asio (coroutines, epoll) | 3.74K ops/s | 0.97% | -4.8%
-| `concurrent_parents/4` | asio (callbacks, epoll) | 3.93K ops/s | 0.83% | baseline (epoll)
-| `concurrent_parents_lockless/1` | corosio (epoll) | 3.73K ops/s | 0.12% | -8.2%
-| `concurrent_parents_lockless/1` | asio (coroutines, epoll) | 3.89K ops/s | 0.28% | -4.5%
-| `concurrent_parents_lockless/1` | asio (callbacks, epoll) | 4.07K ops/s | 0.85% | baseline (epoll)
-| `concurrent_parents_lockless/16` | corosio (epoll) | 3.62K ops/s | 0.81% | -9.2%
-| `concurrent_parents_lockless/16` | asio (coroutines, epoll) | 3.80K ops/s | 0.19% | -4.8%
-| `concurrent_parents_lockless/16` | asio (callbacks, epoll) | 3.99K ops/s | 0.80% | baseline (epoll)
-| `concurrent_parents_lockless/4` | corosio (epoll) | 3.63K ops/s | 0.59% | -8.8%
-| `concurrent_parents_lockless/4` | asio (coroutines, epoll) | 3.80K ops/s | 0.32% | -4.6%
-| `concurrent_parents_lockless/4` | asio (callbacks, epoll) | 3.98K ops/s | 0.87% | baseline (epoll)
+| `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)
|===
====
@@ -276,42 +276,42 @@ image::bench/linux-fan_out-epoll-g2.svg[fan out comparison (epoll), part 2,role=
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `fork_join/1` | corosio (epoll) | 54.81K ops/s | 0.95% | -8.6%
-| `fork_join/1` | asio (coroutines, epoll) | 52.61K ops/s | 0.98% | -12.3%
-| `fork_join/1` | asio (callbacks, epoll) | 59.96K ops/s | 1.01% | baseline (epoll)
-| `fork_join/16` | corosio (epoll) | 3.69K ops/s | 0.21% | -8.2%
-| `fork_join/16` | asio (coroutines, epoll) | 3.84K ops/s | 0.96% | -4.5%
-| `fork_join/16` | asio (callbacks, epoll) | 4.02K ops/s | 0.99% | baseline (epoll)
-| `fork_join/4` | corosio (epoll) | 14.65K ops/s | 0.13% | -7.6%
-| `fork_join/4` | asio (coroutines, epoll) | 14.84K ops/s | 0.98% | -6.4%
-| `fork_join/4` | asio (callbacks, epoll) | 15.85K ops/s | 0.60% | baseline (epoll)
-| `fork_join/64` | corosio (epoll) | 900.2 ops/s | 0.12% | -8.0%
-| `fork_join/64` | asio (coroutines, epoll) | 939.3 ops/s | 0.87% | -4.0%
-| `fork_join/64` | asio (callbacks, epoll) | 978.8 ops/s | 0.92% | baseline (epoll)
-| `fork_join_lockless/1` | corosio (epoll) | 55.61K ops/s | 0.21% | -8.6%
-| `fork_join_lockless/1` | asio (coroutines, epoll) | 53.42K ops/s | 0.69% | -12.2%
-| `fork_join_lockless/1` | asio (callbacks, epoll) | 60.85K ops/s | 0.89% | baseline (epoll)
-| `fork_join_lockless/16` | corosio (epoll) | 3.73K ops/s | 0.82% | -8.5%
-| `fork_join_lockless/16` | asio (coroutines, epoll) | 3.88K ops/s | 0.26% | -4.7%
-| `fork_join_lockless/16` | asio (callbacks, epoll) | 4.08K ops/s | 0.90% | baseline (epoll)
-| `fork_join_lockless/4` | corosio (epoll) | 14.84K ops/s | 0.19% | -7.7%
-| `fork_join_lockless/4` | asio (coroutines, epoll) | 15.05K ops/s | 0.32% | -6.5%
-| `fork_join_lockless/4` | asio (callbacks, epoll) | 16.09K ops/s | 0.86% | baseline (epoll)
-| `fork_join_lockless/64` | corosio (epoll) | 910.3 ops/s | 0.88% | -8.2%
-| `fork_join_lockless/64` | asio (coroutines, epoll) | 952.6 ops/s | 0.18% | -3.9%
-| `fork_join_lockless/64` | asio (callbacks, epoll) | 991.7 ops/s | 0.77% | baseline (epoll)
-| `nested/16` | corosio (epoll) | 893.1 ops/s | 0.88% | -8.4%
-| `nested/16` | asio (coroutines, epoll) | 929.2 ops/s | 0.23% | -4.7%
-| `nested/16` | asio (callbacks, epoll) | 975.4 ops/s | 0.97% | baseline (epoll)
-| `nested/4` | corosio (epoll) | 3.66K ops/s | 0.91% | -8.6%
-| `nested/4` | asio (coroutines, epoll) | 3.78K ops/s | 0.27% | -5.7%
-| `nested/4` | asio (callbacks, epoll) | 4.01K ops/s | 1.03% | baseline (epoll)
-| `nested_lockless/16` | corosio (epoll) | 902.4 ops/s | 0.10% | -9.0%
-| `nested_lockless/16` | asio (coroutines, epoll) | 943.3 ops/s | 0.86% | -4.9%
-| `nested_lockless/16` | asio (callbacks, epoll) | 991.4 ops/s | 0.87% | baseline (epoll)
-| `nested_lockless/4` | corosio (epoll) | 3.71K ops/s | 0.89% | -8.9%
-| `nested_lockless/4` | asio (coroutines, epoll) | 3.84K ops/s | 0.86% | -5.9%
-| `nested_lockless/4` | asio (callbacks, epoll) | 4.08K ops/s | 0.85% | baseline (epoll)
+| `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)
|===
====
@@ -337,39 +337,39 @@ image::bench/linux-http_server-uring.svg[http server comparison (io_uring),role=
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `concurrent/1` | corosio (io_uring) | 53.45K ops/s | 1.33% | +1.3%
-| `concurrent/1` | asio (coroutines, io_uring) | 51.57K ops/s | 1.06% | -2.3%
-| `concurrent/1` | asio (callbacks, io_uring) | 52.77K ops/s | 1.16% | baseline (io_uring)
-| `concurrent/16` | corosio (io_uring) | 52.87K ops/s | 0.99% | -14.0%
-| `concurrent/16` | asio (coroutines, io_uring) | 60.33K ops/s | 0.78% | -1.9%
-| `concurrent/16` | asio (callbacks, io_uring) | 61.50K ops/s | 0.94% | baseline (io_uring)
-| `concurrent/32` | corosio (io_uring) | 52.55K ops/s | 0.83% | -14.5%
-| `concurrent/32` | asio (coroutines, io_uring) | 60.23K ops/s | 1.05% | -2.0%
-| `concurrent/32` | asio (callbacks, io_uring) | 61.44K ops/s | 0.41% | baseline (io_uring)
-| `concurrent/4` | corosio (io_uring) | 53.06K ops/s | 1.22% | -10.9%
-| `concurrent/4` | asio (coroutines, io_uring) | 58.30K ops/s | 0.88% | -2.1%
-| `concurrent/4` | asio (callbacks, io_uring) | 59.57K ops/s | 0.92% | baseline (io_uring)
-| `multithread/1` | corosio (io_uring) | 52.53K ops/s | 0.74% | -14.4%
-| `multithread/1` | asio (coroutines, io_uring) | 60.16K ops/s | 0.78% | -2.0%
-| `multithread/1` | asio (callbacks, io_uring) | 61.39K ops/s | 0.28% | baseline (io_uring)
-| `multithread/16` | corosio (io_uring) | 81.86K ops/s | 13.26% | +90.3%
-| `multithread/16` | asio (coroutines, io_uring) | 40.11K ops/s | 1.71% | -6.7%
-| `multithread/16` | asio (callbacks, io_uring) | 43.01K ops/s | 1.66% | baseline (io_uring)
-| `multithread/2` | corosio (io_uring) | 90.67K ops/s | 0.46% | +91.3%
-| `multithread/2` | asio (coroutines, io_uring) | 47.35K ops/s | 8.15% | -0.1%
-| `multithread/2` | asio (callbacks, io_uring) | 47.41K ops/s | 10.18% | baseline (io_uring)
-| `multithread/4` | corosio (io_uring) | 80.23K ops/s | 0.39% | +72.7%
-| `multithread/4` | asio (coroutines, io_uring) | 45.90K ops/s | 0.35% | -1.2%
-| `multithread/4` | asio (callbacks, io_uring) | 46.46K ops/s | 0.27% | baseline (io_uring)
-| `multithread/8` | corosio (io_uring) | 77.71K ops/s | 0.53% | +78.9%
-| `multithread/8` | asio (coroutines, io_uring) | 41.91K ops/s | 0.95% | -3.5%
-| `multithread/8` | asio (callbacks, io_uring) | 43.43K ops/s | 0.80% | baseline (io_uring)
-| `single_conn` | corosio (io_uring) | 53.68K ops/s | 1.21% | +1.8%
-| `single_conn` | asio (coroutines, io_uring) | 51.56K ops/s | 0.98% | -2.3%
-| `single_conn` | asio (callbacks, io_uring) | 52.75K ops/s | 0.80% | baseline (io_uring)
-| `single_conn_lockless` | corosio (io_uring) | 56.14K ops/s | 1.05% | +4.5%
-| `single_conn_lockless` | asio (coroutines, io_uring) | 52.55K ops/s | 1.11% | -2.2%
-| `single_conn_lockless` | asio (callbacks, io_uring) | 53.74K ops/s | 1.15% | baseline (io_uring)
+| `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)
|===
====
@@ -387,39 +387,39 @@ image::bench/linux-http_server-epoll.svg[http server comparison (epoll),role=bch
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `concurrent/1` | corosio (epoll) | 55.02K ops/s | 0.21% | -6.0%
-| `concurrent/1` | asio (coroutines, epoll) | 57.04K ops/s | 1.14% | -2.6%
-| `concurrent/1` | asio (callbacks, epoll) | 58.53K ops/s | 0.13% | baseline (epoll)
-| `concurrent/16` | corosio (epoll) | 57.82K ops/s | 0.14% | -6.8%
-| `concurrent/16` | asio (coroutines, epoll) | 60.14K ops/s | 1.28% | -3.0%
-| `concurrent/16` | asio (callbacks, epoll) | 62.02K ops/s | 0.73% | baseline (epoll)
-| `concurrent/32` | corosio (epoll) | 57.45K ops/s | 0.13% | -6.6%
-| `concurrent/32` | asio (coroutines, epoll) | 59.51K ops/s | 1.16% | -3.2%
-| `concurrent/32` | asio (callbacks, epoll) | 61.48K ops/s | 0.83% | baseline (epoll)
-| `concurrent/4` | corosio (epoll) | 57.08K ops/s | 0.14% | -7.0%
-| `concurrent/4` | asio (coroutines, epoll) | 60.48K ops/s | 1.27% | -1.5%
-| `concurrent/4` | asio (callbacks, epoll) | 61.37K ops/s | 0.22% | baseline (epoll)
-| `multithread/1` | corosio (epoll) | 57.35K ops/s | 0.59% | -6.7%
-| `multithread/1` | asio (coroutines, epoll) | 59.50K ops/s | 1.08% | -3.2%
-| `multithread/1` | asio (callbacks, epoll) | 61.45K ops/s | 0.89% | baseline (epoll)
-| `multithread/16` | corosio (epoll) | 161.9K ops/s | 0.20% | -1.0%
-| `multithread/16` | asio (coroutines, epoll) | 155.4K ops/s | 0.31% | -4.9%
-| `multithread/16` | asio (callbacks, epoll) | 163.4K ops/s | 0.53% | baseline (epoll)
-| `multithread/2` | corosio (epoll) | 86.93K ops/s | 0.44% | -7.5%
-| `multithread/2` | asio (coroutines, epoll) | 89.12K ops/s | 0.51% | -5.2%
-| `multithread/2` | asio (callbacks, epoll) | 94.00K ops/s | 0.67% | baseline (epoll)
-| `multithread/4` | corosio (epoll) | 160.1K ops/s | 0.47% | -3.4%
-| `multithread/4` | asio (coroutines, epoll) | 157.3K ops/s | 0.61% | -5.1%
-| `multithread/4` | asio (callbacks, epoll) | 165.8K ops/s | 0.65% | baseline (epoll)
-| `multithread/8` | corosio (epoll) | 161.1K ops/s | 0.21% | -1.4%
-| `multithread/8` | asio (coroutines, epoll) | 155.7K ops/s | 0.29% | -4.7%
-| `multithread/8` | asio (callbacks, epoll) | 163.3K ops/s | 0.52% | baseline (epoll)
-| `single_conn` | corosio (epoll) | 55.09K ops/s | 1.04% | -5.9%
-| `single_conn` | asio (coroutines, epoll) | 56.90K ops/s | 0.92% | -2.8%
-| `single_conn` | asio (callbacks, epoll) | 58.56K ops/s | 0.85% | baseline (epoll)
-| `single_conn_lockless` | corosio (epoll) | 55.80K ops/s | 0.46% | -5.9%
-| `single_conn_lockless` | asio (coroutines, epoll) | 57.70K ops/s | 1.10% | -2.7%
-| `single_conn_lockless` | asio (callbacks, epoll) | 59.30K ops/s | 0.98% | baseline (epoll)
+| `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)
|===
====
@@ -445,42 +445,42 @@ image::bench/linux-local_socket_latency-uring.svg[local socket latency compariso
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `concurrent/1` | corosio (io_uring) | 6.56 µs | 4.09% | +25.3%
-| `concurrent/1` | asio (coroutines, io_uring) | 9.22 µs | 2.67% | -5.0%
-| `concurrent/1` | asio (callbacks, io_uring) | 8.78 µs | 0.16% | baseline (io_uring)
-| `concurrent/16` | corosio (io_uring) | 108.34 µs | 1.05% | -6.5%
-| `concurrent/16` | asio (coroutines, io_uring) | 105.53 µs | 0.75% | -3.7%
-| `concurrent/16` | asio (callbacks, io_uring) | 101.74 µs | 0.75% | baseline (io_uring)
-| `concurrent/4` | corosio (io_uring) | 26.94 µs | 1.58% | +1.8%
-| `concurrent/4` | asio (coroutines, io_uring) | 28.20 µs | 1.47% | -2.8%
-| `concurrent/4` | asio (callbacks, io_uring) | 27.43 µs | 1.11% | baseline (io_uring)
-| `concurrent_lockless/1` | corosio (io_uring) | 6.55 µs | 4.18% | +23.7%
-| `concurrent_lockless/1` | asio (coroutines, io_uring) | 8.77 µs | 3.11% | -2.2%
-| `concurrent_lockless/1` | asio (callbacks, io_uring) | 8.58 µs | 3.48% | baseline (io_uring)
-| `concurrent_lockless/16` | corosio (io_uring) | 108.13 µs | 0.82% | -10.7%
-| `concurrent_lockless/16` | asio (coroutines, io_uring) | 102.49 µs | 1.04% | -5.0%
-| `concurrent_lockless/16` | asio (callbacks, io_uring) | 97.65 µs | 0.84% | baseline (io_uring)
-| `concurrent_lockless/4` | corosio (io_uring) | 27.08 µs | 0.88% | -2.6%
-| `concurrent_lockless/4` | asio (coroutines, io_uring) | 27.52 µs | 1.41% | -4.3%
-| `concurrent_lockless/4` | asio (callbacks, io_uring) | 26.39 µs | 0.74% | baseline (io_uring)
-| `pingpong/1` | corosio (io_uring) | 6.53 µs | 3.23% | +25.5%
-| `pingpong/1` | asio (coroutines, io_uring) | 9.08 µs | 2.60% | -3.6%
-| `pingpong/1` | asio (callbacks, io_uring) | 8.76 µs | 3.62% | baseline (io_uring)
-| `pingpong/1024` | corosio (io_uring) | 7.43 µs | 5.34% | +19.5%
-| `pingpong/1024` | asio (coroutines, io_uring) | 9.99 µs | 3.17% | -8.2%
-| `pingpong/1024` | asio (callbacks, io_uring) | 9.23 µs | 3.64% | baseline (io_uring)
-| `pingpong/64` | corosio (io_uring) | 6.59 µs | 4.50% | +24.9%
-| `pingpong/64` | asio (coroutines, io_uring) | 9.18 µs | 1.08% | -4.6%
-| `pingpong/64` | asio (callbacks, io_uring) | 8.78 µs | 3.19% | baseline (io_uring)
-| `pingpong_lockless/1` | corosio (io_uring) | 6.53 µs | 4.41% | +21.0%
-| `pingpong_lockless/1` | asio (coroutines, io_uring) | 8.73 µs | 3.80% | -5.6%
-| `pingpong_lockless/1` | asio (callbacks, io_uring) | 8.27 µs | 2.59% | baseline (io_uring)
-| `pingpong_lockless/1024` | corosio (io_uring) | 7.45 µs | 4.84% | +19.0%
-| `pingpong_lockless/1024` | asio (coroutines, io_uring) | 9.04 µs | 4.01% | +1.7%
-| `pingpong_lockless/1024` | asio (callbacks, io_uring) | 9.20 µs | 2.66% | baseline (io_uring)
-| `pingpong_lockless/64` | corosio (io_uring) | 6.56 µs | 3.76% | +21.0%
-| `pingpong_lockless/64` | asio (coroutines, io_uring) | 8.77 µs | 2.99% | -5.5%
-| `pingpong_lockless/64` | asio (callbacks, io_uring) | 8.31 µs | 0.28% | baseline (io_uring)
+| `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)
|===
====
@@ -498,42 +498,42 @@ image::bench/linux-local_socket_latency-epoll.svg[local socket latency compariso
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `concurrent/1` | corosio (epoll) | 7.11 µs | 3.77% | +13.4%
-| `concurrent/1` | asio (coroutines, epoll) | 8.60 µs | 3.20% | -4.6%
-| `concurrent/1` | asio (callbacks, epoll) | 8.22 µs | 3.11% | baseline (epoll)
-| `concurrent/16` | corosio (epoll) | 110.13 µs | 0.73% | -4.5%
-| `concurrent/16` | asio (coroutines, epoll) | 112.84 µs | 0.71% | -7.1%
-| `concurrent/16` | asio (callbacks, epoll) | 105.39 µs | 0.75% | baseline (epoll)
-| `concurrent/4` | corosio (epoll) | 27.52 µs | 1.65% | +1.0%
-| `concurrent/4` | asio (coroutines, epoll) | 29.61 µs | 1.67% | -6.5%
-| `concurrent/4` | asio (callbacks, epoll) | 27.79 µs | 1.31% | baseline (epoll)
-| `concurrent_lockless/1` | corosio (epoll) | 7.00 µs | 4.74% | +11.4%
-| `concurrent_lockless/1` | asio (coroutines, epoll) | 8.29 µs | 3.82% | -5.0%
-| `concurrent_lockless/1` | asio (callbacks, epoll) | 7.90 µs | 1.09% | baseline (epoll)
-| `concurrent_lockless/16` | corosio (epoll) | 108.75 µs | 0.34% | -7.5%
-| `concurrent_lockless/16` | asio (coroutines, epoll) | 107.97 µs | 0.77% | -6.7%
-| `concurrent_lockless/16` | asio (callbacks, epoll) | 101.16 µs | 1.07% | baseline (epoll)
-| `concurrent_lockless/4` | corosio (epoll) | 27.60 µs | 1.36% | -4.9%
-| `concurrent_lockless/4` | asio (coroutines, epoll) | 28.47 µs | 0.49% | -8.2%
-| `concurrent_lockless/4` | asio (callbacks, epoll) | 26.31 µs | 1.67% | baseline (epoll)
-| `pingpong/1` | corosio (epoll) | 7.07 µs | 3.51% | +13.7%
-| `pingpong/1` | asio (coroutines, epoll) | 8.56 µs | 3.08% | -4.5%
-| `pingpong/1` | asio (callbacks, epoll) | 8.19 µs | 3.62% | baseline (epoll)
-| `pingpong/1024` | corosio (epoll) | 7.36 µs | 4.39% | +17.7%
-| `pingpong/1024` | asio (coroutines, epoll) | 9.50 µs | 3.30% | -6.1%
-| `pingpong/1024` | asio (callbacks, epoll) | 8.95 µs | 3.55% | baseline (epoll)
-| `pingpong/64` | corosio (epoll) | 7.11 µs | 0.18% | +13.5%
-| `pingpong/64` | asio (coroutines, epoll) | 8.61 µs | 3.70% | -4.8%
-| `pingpong/64` | asio (callbacks, epoll) | 8.22 µs | 0.84% | baseline (epoll)
-| `pingpong_lockless/1` | corosio (epoll) | 6.96 µs | 5.13% | +11.7%
-| `pingpong_lockless/1` | asio (coroutines, epoll) | 8.22 µs | 3.88% | -4.3%
-| `pingpong_lockless/1` | asio (callbacks, epoll) | 7.88 µs | 4.43% | baseline (epoll)
-| `pingpong_lockless/1024` | corosio (epoll) | 7.85 µs | 2.88% | +10.9%
-| `pingpong_lockless/1024` | asio (coroutines, epoll) | 9.19 µs | 2.99% | -4.3%
-| `pingpong_lockless/1024` | asio (callbacks, epoll) | 8.81 µs | 2.58% | baseline (epoll)
-| `pingpong_lockless/64` | corosio (epoll) | 7.51 µs | 4.31% | +5.0%
-| `pingpong_lockless/64` | asio (coroutines, epoll) | 8.28 µs | 4.12% | -4.7%
-| `pingpong_lockless/64` | asio (callbacks, epoll) | 7.90 µs | 4.42% | baseline (epoll)
+| `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)
|===
====
@@ -559,42 +559,42 @@ image::bench/linux-local_socket_throughput-uring-g1.svg[local socket throughput
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `bidirectional/1024` | corosio (io_uring) | 302.6 MB/s | 1.03% | +10.3%
-| `bidirectional/1024` | asio (coroutines, io_uring) | 260.4 MB/s | 5.00% | -5.1%
-| `bidirectional/1024` | asio (callbacks, io_uring) | 274.3 MB/s | 3.34% | baseline (io_uring)
-| `bidirectional/1048576` | corosio (io_uring) | 3.31 GB/s | 1.57% | -4.8%
-| `bidirectional/1048576` | asio (coroutines, io_uring) | 3.53 GB/s | 2.27% | +1.5%
-| `bidirectional/1048576` | asio (callbacks, io_uring) | 3.47 GB/s | 2.38% | baseline (io_uring)
-| `bidirectional/16384` | corosio (io_uring) | 2.42 GB/s | 1.24% | -16.1%
-| `bidirectional/16384` | asio (coroutines, io_uring) | 2.88 GB/s | 2.69% | -0.2%
-| `bidirectional/16384` | asio (callbacks, io_uring) | 2.88 GB/s | 1.71% | baseline (io_uring)
-| `bidirectional/262144` | corosio (io_uring) | 3.30 GB/s | 1.11% | -5.6%
-| `bidirectional/262144` | asio (coroutines, io_uring) | 3.52 GB/s | 1.94% | +0.5%
-| `bidirectional/262144` | asio (callbacks, io_uring) | 3.50 GB/s | 2.59% | baseline (io_uring)
-| `bidirectional/4096` | corosio (io_uring) | 996.0 MB/s | 1.15% | +7.0%
-| `bidirectional/4096` | asio (coroutines, io_uring) | 900.3 MB/s | 2.84% | -3.3%
-| `bidirectional/4096` | asio (callbacks, io_uring) | 930.6 MB/s | 2.89% | baseline (io_uring)
-| `bidirectional/65536` | corosio (io_uring) | 3.02 GB/s | 2.29% | -20.0%
-| `bidirectional/65536` | asio (coroutines, io_uring) | 3.72 GB/s | 4.19% | -1.6%
-| `bidirectional/65536` | asio (callbacks, io_uring) | 3.77 GB/s | 2.09% | baseline (io_uring)
-| `bidirectional_lockless/1024` | corosio (io_uring) | 303.0 MB/s | 0.32% | +4.9%
-| `bidirectional_lockless/1024` | asio (coroutines, io_uring) | 295.7 MB/s | 3.42% | +2.4%
-| `bidirectional_lockless/1024` | asio (callbacks, io_uring) | 288.8 MB/s | 4.79% | baseline (io_uring)
-| `bidirectional_lockless/1048576` | corosio (io_uring) | 3.41 GB/s | 2.52% | -4.2%
-| `bidirectional_lockless/1048576` | asio (coroutines, io_uring) | 3.53 GB/s | 1.21% | -0.9%
-| `bidirectional_lockless/1048576` | asio (callbacks, io_uring) | 3.56 GB/s | 2.31% | baseline (io_uring)
-| `bidirectional_lockless/16384` | corosio (io_uring) | 2.64 GB/s | 1.44% | -9.9%
-| `bidirectional_lockless/16384` | asio (coroutines, io_uring) | 2.93 GB/s | 1.86% | +0.2%
-| `bidirectional_lockless/16384` | asio (callbacks, io_uring) | 2.93 GB/s | 2.88% | baseline (io_uring)
-| `bidirectional_lockless/262144` | corosio (io_uring) | 3.38 GB/s | 1.45% | -5.5%
-| `bidirectional_lockless/262144` | asio (coroutines, io_uring) | 3.57 GB/s | 2.53% | -0.3%
-| `bidirectional_lockless/262144` | asio (callbacks, io_uring) | 3.58 GB/s | 2.74% | baseline (io_uring)
-| `bidirectional_lockless/4096` | corosio (io_uring) | 999.9 MB/s | 0.56% | +11.6%
-| `bidirectional_lockless/4096` | asio (coroutines, io_uring) | 925.8 MB/s | 2.49% | +3.3%
-| `bidirectional_lockless/4096` | asio (callbacks, io_uring) | 895.8 MB/s | 4.44% | baseline (io_uring)
-| `bidirectional_lockless/65536` | corosio (io_uring) | 3.21 GB/s | 1.77% | -14.8%
-| `bidirectional_lockless/65536` | asio (coroutines, io_uring) | 3.76 GB/s | 4.44% | -0.2%
-| `bidirectional_lockless/65536` | asio (callbacks, io_uring) | 3.77 GB/s | 2.17% | baseline (io_uring)
+| `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)
|===
====
@@ -610,42 +610,42 @@ image::bench/linux-local_socket_throughput-uring-g2.svg[local socket throughput
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `unidirectional/1024` | corosio (io_uring) | 303.5 MB/s | 0.82% | +15.0%
-| `unidirectional/1024` | asio (coroutines, io_uring) | 240.0 MB/s | 3.83% | -9.0%
-| `unidirectional/1024` | asio (callbacks, io_uring) | 263.8 MB/s | 3.17% | baseline (io_uring)
-| `unidirectional/1048576` | corosio (io_uring) | 3.42 GB/s | 3.01% | -3.5%
-| `unidirectional/1048576` | asio (coroutines, io_uring) | 3.54 GB/s | 2.17% | -0.1%
-| `unidirectional/1048576` | asio (callbacks, io_uring) | 3.54 GB/s | 2.60% | baseline (io_uring)
-| `unidirectional/16384` | corosio (io_uring) | 2.67 GB/s | 2.34% | -4.0%
-| `unidirectional/16384` | asio (coroutines, io_uring) | 2.73 GB/s | 2.13% | -1.7%
-| `unidirectional/16384` | asio (callbacks, io_uring) | 2.78 GB/s | 3.80% | baseline (io_uring)
-| `unidirectional/262144` | corosio (io_uring) | 3.46 GB/s | 1.32% | -1.9%
-| `unidirectional/262144` | asio (coroutines, io_uring) | 3.55 GB/s | 1.01% | +0.7%
-| `unidirectional/262144` | asio (callbacks, io_uring) | 3.53 GB/s | 2.29% | baseline (io_uring)
-| `unidirectional/4096` | corosio (io_uring) | 1.00 GB/s | 1.12% | +14.9%
-| `unidirectional/4096` | asio (coroutines, io_uring) | 845.2 MB/s | 3.36% | -3.0%
-| `unidirectional/4096` | asio (callbacks, io_uring) | 870.9 MB/s | 0.72% | baseline (io_uring)
-| `unidirectional/65536` | corosio (io_uring) | 3.32 GB/s | 3.03% | -15.9%
-| `unidirectional/65536` | asio (coroutines, io_uring) | 3.95 GB/s | 5.85% | -0.1%
-| `unidirectional/65536` | asio (callbacks, io_uring) | 3.95 GB/s | 3.95% | baseline (io_uring)
-| `unidirectional_lockless/1024` | corosio (io_uring) | 304.2 MB/s | 0.88% | +16.8%
-| `unidirectional_lockless/1024` | asio (coroutines, io_uring) | 269.5 MB/s | 4.38% | +3.4%
-| `unidirectional_lockless/1024` | asio (callbacks, io_uring) | 260.6 MB/s | 4.69% | baseline (io_uring)
-| `unidirectional_lockless/1048576` | corosio (io_uring) | 3.41 GB/s | 2.81% | -4.2%
-| `unidirectional_lockless/1048576` | asio (coroutines, io_uring) | 3.56 GB/s | 1.41% | +0.1%
-| `unidirectional_lockless/1048576` | asio (callbacks, io_uring) | 3.56 GB/s | 2.67% | baseline (io_uring)
-| `unidirectional_lockless/16384` | corosio (io_uring) | 2.65 GB/s | 1.33% | -5.1%
-| `unidirectional_lockless/16384` | asio (coroutines, io_uring) | 2.83 GB/s | 0.69% | +1.4%
-| `unidirectional_lockless/16384` | asio (callbacks, io_uring) | 2.79 GB/s | 2.48% | baseline (io_uring)
-| `unidirectional_lockless/262144` | corosio (io_uring) | 3.45 GB/s | 1.24% | -3.2%
-| `unidirectional_lockless/262144` | asio (coroutines, io_uring) | 3.56 GB/s | 1.25% | +0.0%
-| `unidirectional_lockless/262144` | asio (callbacks, io_uring) | 3.56 GB/s | 2.67% | baseline (io_uring)
-| `unidirectional_lockless/4096` | corosio (io_uring) | 1.00 GB/s | 0.67% | +11.3%
-| `unidirectional_lockless/4096` | asio (coroutines, io_uring) | 872.1 MB/s | 2.14% | -3.0%
-| `unidirectional_lockless/4096` | asio (callbacks, io_uring) | 899.2 MB/s | 3.15% | baseline (io_uring)
-| `unidirectional_lockless/65536` | corosio (io_uring) | 3.28 GB/s | 1.64% | -17.7%
-| `unidirectional_lockless/65536` | asio (coroutines, io_uring) | 3.99 GB/s | 5.86% | +0.2%
-| `unidirectional_lockless/65536` | asio (callbacks, io_uring) | 3.98 GB/s | 4.49% | baseline (io_uring)
+| `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)
|===
====
@@ -663,42 +663,42 @@ image::bench/linux-local_socket_throughput-epoll-g1.svg[local socket throughput
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `bidirectional/1024` | corosio (epoll) | 304.3 MB/s | 0.78% | +3.2%
-| `bidirectional/1024` | asio (coroutines, epoll) | 263.6 MB/s | 4.34% | -10.6%
-| `bidirectional/1024` | asio (callbacks, epoll) | 294.8 MB/s | 2.68% | baseline (epoll)
-| `bidirectional/1048576` | corosio (epoll) | 3.13 GB/s | 1.70% | -5.0%
-| `bidirectional/1048576` | asio (coroutines, epoll) | 3.20 GB/s | 2.51% | -2.8%
-| `bidirectional/1048576` | asio (callbacks, epoll) | 3.30 GB/s | 3.22% | baseline (epoll)
-| `bidirectional/16384` | corosio (epoll) | 3.03 GB/s | 1.53% | +1.7%
-| `bidirectional/16384` | asio (coroutines, epoll) | 2.83 GB/s | 2.51% | -4.9%
-| `bidirectional/16384` | asio (callbacks, epoll) | 2.98 GB/s | 2.72% | baseline (epoll)
-| `bidirectional/262144` | corosio (epoll) | 3.13 GB/s | 1.23% | -4.5%
-| `bidirectional/262144` | asio (coroutines, epoll) | 3.27 GB/s | 2.17% | -0.3%
-| `bidirectional/262144` | asio (callbacks, epoll) | 3.28 GB/s | 4.57% | baseline (epoll)
-| `bidirectional/4096` | corosio (epoll) | 1.00 GB/s | 0.46% | +7.6%
-| `bidirectional/4096` | asio (coroutines, epoll) | 888.2 MB/s | 2.87% | -4.7%
-| `bidirectional/4096` | asio (callbacks, epoll) | 932.4 MB/s | 3.54% | baseline (epoll)
-| `bidirectional/65536` | corosio (epoll) | 2.98 GB/s | 1.58% | -18.0%
-| `bidirectional/65536` | asio (coroutines, epoll) | 3.60 GB/s | 1.68% | -1.0%
-| `bidirectional/65536` | asio (callbacks, epoll) | 3.64 GB/s | 2.98% | baseline (epoll)
-| `bidirectional_lockless/1024` | corosio (epoll) | 305.2 MB/s | 1.08% | +7.3%
-| `bidirectional_lockless/1024` | asio (coroutines, epoll) | 265.0 MB/s | 5.06% | -6.8%
-| `bidirectional_lockless/1024` | asio (callbacks, epoll) | 284.4 MB/s | 4.56% | baseline (epoll)
-| `bidirectional_lockless/1048576` | corosio (epoll) | 3.16 GB/s | 0.89% | -3.4%
-| `bidirectional_lockless/1048576` | asio (coroutines, epoll) | 3.22 GB/s | 2.67% | -1.5%
-| `bidirectional_lockless/1048576` | asio (callbacks, epoll) | 3.27 GB/s | 4.06% | baseline (epoll)
-| `bidirectional_lockless/16384` | corosio (epoll) | 3.11 GB/s | 2.10% | +1.9%
-| `bidirectional_lockless/16384` | asio (coroutines, epoll) | 2.90 GB/s | 2.33% | -5.2%
-| `bidirectional_lockless/16384` | asio (callbacks, epoll) | 3.06 GB/s | 1.54% | baseline (epoll)
-| `bidirectional_lockless/262144` | corosio (epoll) | 3.12 GB/s | 2.30% | -4.5%
-| `bidirectional_lockless/262144` | asio (coroutines, epoll) | 3.28 GB/s | 2.37% | +0.4%
-| `bidirectional_lockless/262144` | asio (callbacks, epoll) | 3.27 GB/s | 4.17% | baseline (epoll)
-| `bidirectional_lockless/4096` | corosio (epoll) | 1.01 GB/s | 0.84% | +6.6%
-| `bidirectional_lockless/4096` | asio (coroutines, epoll) | 910.5 MB/s | 3.20% | -4.1%
-| `bidirectional_lockless/4096` | asio (callbacks, epoll) | 949.8 MB/s | 3.41% | baseline (epoll)
-| `bidirectional_lockless/65536` | corosio (epoll) | 3.00 GB/s | 1.86% | -19.2%
-| `bidirectional_lockless/65536` | asio (coroutines, epoll) | 3.61 GB/s | 2.91% | -2.8%
-| `bidirectional_lockless/65536` | asio (callbacks, epoll) | 3.72 GB/s | 3.56% | baseline (epoll)
+| `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)
|===
====
@@ -714,42 +714,42 @@ image::bench/linux-local_socket_throughput-epoll-g2.svg[local socket throughput
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `unidirectional/1024` | corosio (epoll) | 298.4 MB/s | 0.96% | +16.1%
-| `unidirectional/1024` | asio (coroutines, epoll) | 240.9 MB/s | 3.83% | -6.3%
-| `unidirectional/1024` | asio (callbacks, epoll) | 257.0 MB/s | 4.28% | baseline (epoll)
-| `unidirectional/1048576` | corosio (epoll) | 3.25 GB/s | 1.31% | -6.3%
-| `unidirectional/1048576` | asio (coroutines, epoll) | 3.39 GB/s | 2.40% | -2.3%
-| `unidirectional/1048576` | asio (callbacks, epoll) | 3.47 GB/s | 3.83% | baseline (epoll)
-| `unidirectional/16384` | corosio (epoll) | 3.08 GB/s | 1.51% | +7.9%
-| `unidirectional/16384` | asio (coroutines, epoll) | 2.76 GB/s | 2.62% | -3.4%
-| `unidirectional/16384` | asio (callbacks, epoll) | 2.86 GB/s | 1.81% | baseline (epoll)
-| `unidirectional/262144` | corosio (epoll) | 3.27 GB/s | 1.66% | -5.6%
-| `unidirectional/262144` | asio (coroutines, epoll) | 3.37 GB/s | 1.67% | -2.7%
-| `unidirectional/262144` | asio (callbacks, epoll) | 3.46 GB/s | 3.93% | baseline (epoll)
-| `unidirectional/4096` | corosio (epoll) | 978.7 MB/s | 1.06% | +11.0%
-| `unidirectional/4096` | asio (coroutines, epoll) | 842.7 MB/s | 2.71% | -4.4%
-| `unidirectional/4096` | asio (callbacks, epoll) | 881.8 MB/s | 0.49% | baseline (epoll)
-| `unidirectional/65536` | corosio (epoll) | 3.29 GB/s | 2.35% | -13.9%
-| `unidirectional/65536` | asio (coroutines, epoll) | 3.83 GB/s | 2.77% | +0.2%
-| `unidirectional/65536` | asio (callbacks, epoll) | 3.82 GB/s | 2.69% | baseline (epoll)
-| `unidirectional_lockless/1024` | corosio (epoll) | 299.0 MB/s | 0.71% | +12.9%
-| `unidirectional_lockless/1024` | asio (coroutines, epoll) | 250.0 MB/s | 4.40% | -5.6%
-| `unidirectional_lockless/1024` | asio (callbacks, epoll) | 264.9 MB/s | 4.61% | baseline (epoll)
-| `unidirectional_lockless/1048576` | corosio (epoll) | 3.28 GB/s | 1.05% | -4.1%
-| `unidirectional_lockless/1048576` | asio (coroutines, epoll) | 3.36 GB/s | 1.57% | -1.6%
-| `unidirectional_lockless/1048576` | asio (callbacks, epoll) | 3.42 GB/s | 3.36% | baseline (epoll)
-| `unidirectional_lockless/16384` | corosio (epoll) | 3.09 GB/s | 3.18% | +5.8%
-| `unidirectional_lockless/16384` | asio (coroutines, epoll) | 2.81 GB/s | 1.94% | -3.8%
-| `unidirectional_lockless/16384` | asio (callbacks, epoll) | 2.92 GB/s | 2.13% | baseline (epoll)
-| `unidirectional_lockless/262144` | corosio (epoll) | 3.28 GB/s | 1.37% | -5.9%
-| `unidirectional_lockless/262144` | asio (coroutines, epoll) | 3.34 GB/s | 3.68% | -4.2%
-| `unidirectional_lockless/262144` | asio (callbacks, epoll) | 3.48 GB/s | 4.09% | baseline (epoll)
-| `unidirectional_lockless/4096` | corosio (epoll) | 988.0 MB/s | 0.93% | +13.2%
-| `unidirectional_lockless/4096` | asio (coroutines, epoll) | 869.2 MB/s | 2.52% | -0.4%
-| `unidirectional_lockless/4096` | asio (callbacks, epoll) | 873.0 MB/s | 2.70% | baseline (epoll)
-| `unidirectional_lockless/65536` | corosio (epoll) | 3.29 GB/s | 4.33% | -14.8%
-| `unidirectional_lockless/65536` | asio (coroutines, epoll) | 3.92 GB/s | 1.70% | +1.4%
-| `unidirectional_lockless/65536` | asio (callbacks, epoll) | 3.86 GB/s | 3.97% | baseline (epoll)
+| `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)
|===
====
@@ -775,42 +775,42 @@ image::bench/linux-socket_latency-uring.svg[socket latency comparison (io_uring)
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `concurrent/1` | corosio (io_uring) | 14.57 µs | 0.98% | +13.3%
-| `concurrent/1` | asio (coroutines, io_uring) | 17.13 µs | 0.50% | -2.0%
-| `concurrent/1` | asio (callbacks, io_uring) | 16.81 µs | 1.22% | baseline (io_uring)
-| `concurrent/16` | corosio (io_uring) | 236.38 µs | 0.79% | -3.8%
-| `concurrent/16` | asio (coroutines, io_uring) | 232.68 µs | 0.92% | -2.2%
-| `concurrent/16` | asio (callbacks, io_uring) | 227.64 µs | 0.96% | baseline (io_uring)
-| `concurrent/4` | corosio (io_uring) | 58.57 µs | 0.71% | +0.5%
-| `concurrent/4` | asio (coroutines, io_uring) | 60.22 µs | 0.94% | -2.3%
-| `concurrent/4` | asio (callbacks, io_uring) | 58.84 µs | 0.87% | baseline (io_uring)
-| `concurrent_lockless/1` | corosio (io_uring) | 14.58 µs | 1.06% | +10.7%
-| `concurrent_lockless/1` | asio (coroutines, io_uring) | 16.70 µs | 1.06% | -2.3%
-| `concurrent_lockless/1` | asio (callbacks, io_uring) | 16.33 µs | 0.86% | baseline (io_uring)
-| `concurrent_lockless/16` | corosio (io_uring) | 235.72 µs | 1.04% | -5.0%
-| `concurrent_lockless/16` | asio (coroutines, io_uring) | 228.57 µs | 1.04% | -1.8%
-| `concurrent_lockless/16` | asio (callbacks, io_uring) | 224.43 µs | 1.01% | baseline (io_uring)
-| `concurrent_lockless/4` | corosio (io_uring) | 58.50 µs | 1.02% | -1.2%
-| `concurrent_lockless/4` | asio (coroutines, io_uring) | 59.27 µs | 1.28% | -2.5%
-| `concurrent_lockless/4` | asio (callbacks, io_uring) | 57.81 µs | 1.11% | baseline (io_uring)
-| `pingpong/1` | corosio (io_uring) | 14.52 µs | 1.27% | +13.3%
-| `pingpong/1` | asio (coroutines, io_uring) | 17.04 µs | 1.15% | -1.7%
-| `pingpong/1` | asio (callbacks, io_uring) | 16.75 µs | 0.11% | baseline (io_uring)
-| `pingpong/1024` | corosio (io_uring) | 14.81 µs | 1.36% | +13.3%
-| `pingpong/1024` | asio (coroutines, io_uring) | 17.46 µs | 0.82% | -2.2%
-| `pingpong/1024` | asio (callbacks, io_uring) | 17.09 µs | 0.65% | baseline (io_uring)
-| `pingpong/64` | corosio (io_uring) | 14.59 µs | 1.34% | +13.2%
-| `pingpong/64` | asio (coroutines, io_uring) | 17.14 µs | 0.86% | -1.9%
-| `pingpong/64` | asio (callbacks, io_uring) | 16.81 µs | 0.26% | baseline (io_uring)
-| `pingpong_lockless/1` | corosio (io_uring) | 14.49 µs | 1.33% | +10.8%
-| `pingpong_lockless/1` | asio (coroutines, io_uring) | 16.64 µs | 1.06% | -2.5%
-| `pingpong_lockless/1` | asio (callbacks, io_uring) | 16.24 µs | 1.05% | baseline (io_uring)
-| `pingpong_lockless/1024` | corosio (io_uring) | 14.81 µs | 1.19% | +10.8%
-| `pingpong_lockless/1024` | asio (coroutines, io_uring) | 17.01 µs | 0.27% | -2.5%
-| `pingpong_lockless/1024` | asio (callbacks, io_uring) | 16.59 µs | 1.12% | baseline (io_uring)
-| `pingpong_lockless/64` | corosio (io_uring) | 14.56 µs | 1.35% | +10.6%
-| `pingpong_lockless/64` | asio (coroutines, io_uring) | 16.73 µs | 0.21% | -2.7%
-| `pingpong_lockless/64` | asio (callbacks, io_uring) | 16.29 µs | 0.97% | baseline (io_uring)
+| `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)
|===
====
@@ -828,42 +828,42 @@ image::bench/linux-socket_latency-epoll.svg[socket latency comparison (epoll),ro
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `concurrent/1` | corosio (epoll) | 14.80 µs | 0.88% | +7.1%
-| `concurrent/1` | asio (coroutines, epoll) | 16.32 µs | 0.92% | -2.4%
-| `concurrent/1` | asio (callbacks, epoll) | 15.94 µs | 0.61% | baseline (epoll)
-| `concurrent/16` | corosio (epoll) | 232.79 µs | 0.98% | -1.4%
-| `concurrent/16` | asio (coroutines, epoll) | 236.30 µs | 0.99% | -2.9%
-| `concurrent/16` | asio (callbacks, epoll) | 229.53 µs | 0.71% | baseline (epoll)
-| `concurrent/4` | corosio (epoll) | 58.22 µs | 0.88% | +0.4%
-| `concurrent/4` | asio (coroutines, epoll) | 60.27 µs | 1.02% | -3.1%
-| `concurrent/4` | asio (callbacks, epoll) | 58.48 µs | 0.79% | baseline (epoll)
-| `concurrent_lockless/1` | corosio (epoll) | 14.69 µs | 1.26% | +6.0%
-| `concurrent_lockless/1` | asio (coroutines, epoll) | 16.00 µs | 0.81% | -2.4%
-| `concurrent_lockless/1` | asio (callbacks, epoll) | 15.63 µs | 0.97% | baseline (epoll)
-| `concurrent_lockless/16` | corosio (epoll) | 231.82 µs | 1.01% | -3.3%
-| `concurrent_lockless/16` | asio (coroutines, epoll) | 231.30 µs | 1.07% | -3.1%
-| `concurrent_lockless/16` | asio (callbacks, epoll) | 224.45 µs | 0.91% | baseline (epoll)
-| `concurrent_lockless/4` | corosio (epoll) | 57.92 µs | 1.30% | -1.3%
-| `concurrent_lockless/4` | asio (coroutines, epoll) | 59.00 µs | 0.95% | -3.1%
-| `concurrent_lockless/4` | asio (callbacks, epoll) | 57.20 µs | 1.03% | baseline (epoll)
-| `pingpong/1` | corosio (epoll) | 14.74 µs | 1.03% | +7.2%
-| `pingpong/1` | asio (coroutines, epoll) | 16.29 µs | 1.32% | -2.5%
-| `pingpong/1` | asio (callbacks, epoll) | 15.88 µs | 1.06% | baseline (epoll)
-| `pingpong/1024` | corosio (epoll) | 15.04 µs | 1.18% | +7.3%
-| `pingpong/1024` | asio (coroutines, epoll) | 16.56 µs | 0.99% | -2.1%
-| `pingpong/1024` | asio (callbacks, epoll) | 16.22 µs | 0.98% | baseline (epoll)
-| `pingpong/64` | corosio (epoll) | 14.78 µs | 1.17% | +7.3%
-| `pingpong/64` | asio (coroutines, epoll) | 16.35 µs | 1.26% | -2.6%
-| `pingpong/64` | asio (callbacks, epoll) | 15.94 µs | 0.90% | baseline (epoll)
-| `pingpong_lockless/1` | corosio (epoll) | 14.62 µs | 0.99% | +5.8%
-| `pingpong_lockless/1` | asio (coroutines, epoll) | 15.92 µs | 0.79% | -2.5%
-| `pingpong_lockless/1` | asio (callbacks, epoll) | 15.52 µs | 0.86% | baseline (epoll)
-| `pingpong_lockless/1024` | corosio (epoll) | 14.96 µs | 0.95% | +5.8%
-| `pingpong_lockless/1024` | asio (coroutines, epoll) | 16.26 µs | 0.90% | -2.4%
-| `pingpong_lockless/1024` | asio (callbacks, epoll) | 15.89 µs | 0.12% | baseline (epoll)
-| `pingpong_lockless/64` | corosio (epoll) | 14.71 µs | 0.98% | +5.8%
-| `pingpong_lockless/64` | asio (coroutines, epoll) | 16.01 µs | 0.66% | -2.5%
-| `pingpong_lockless/64` | asio (callbacks, epoll) | 15.61 µs | 0.18% | baseline (epoll)
+| `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)
|===
====
@@ -889,42 +889,42 @@ image::bench/linux-socket_throughput-uring-g1.svg[socket throughput comparison (
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `bidirectional/1024` | corosio (io_uring) | 140.6 MB/s | 1.04% | +2.9%
-| `bidirectional/1024` | asio (coroutines, io_uring) | 134.2 MB/s | 1.24% | -1.8%
-| `bidirectional/1024` | asio (callbacks, io_uring) | 136.6 MB/s | 0.45% | baseline (io_uring)
-| `bidirectional/1048576` | corosio (io_uring) | 3.26 GB/s | 1.47% | -0.7%
-| `bidirectional/1048576` | asio (coroutines, io_uring) | 3.25 GB/s | 0.88% | -0.8%
-| `bidirectional/1048576` | asio (callbacks, io_uring) | 3.28 GB/s | 0.86% | baseline (io_uring)
-| `bidirectional/16384` | corosio (io_uring) | 1.54 GB/s | 0.62% | -6.2%
-| `bidirectional/16384` | asio (coroutines, io_uring) | 1.56 GB/s | 0.47% | -5.1%
-| `bidirectional/16384` | asio (callbacks, io_uring) | 1.64 GB/s | 1.87% | baseline (io_uring)
-| `bidirectional/262144` | corosio (io_uring) | 3.21 GB/s | 1.11% | +10.8%
-| `bidirectional/262144` | asio (coroutines, io_uring) | 2.86 GB/s | 0.72% | -1.1%
-| `bidirectional/262144` | asio (callbacks, io_uring) | 2.89 GB/s | 1.61% | baseline (io_uring)
-| `bidirectional/4096` | corosio (io_uring) | 494.8 MB/s | 1.09% | +0.4%
-| `bidirectional/4096` | asio (coroutines, io_uring) | 485.4 MB/s | 1.25% | -1.5%
-| `bidirectional/4096` | asio (callbacks, io_uring) | 492.8 MB/s | 1.39% | baseline (io_uring)
-| `bidirectional/65536` | corosio (io_uring) | 2.76 GB/s | 2.00% | +5.0%
-| `bidirectional/65536` | asio (coroutines, io_uring) | 2.60 GB/s | 1.95% | -1.0%
-| `bidirectional/65536` | asio (callbacks, io_uring) | 2.63 GB/s | 2.11% | baseline (io_uring)
-| `bidirectional_lockless/1024` | corosio (io_uring) | 140.8 MB/s | 0.18% | +0.9%
-| `bidirectional_lockless/1024` | asio (coroutines, io_uring) | 136.4 MB/s | 0.13% | -2.2%
-| `bidirectional_lockless/1024` | asio (callbacks, io_uring) | 139.5 MB/s | 1.34% | baseline (io_uring)
-| `bidirectional_lockless/1048576` | corosio (io_uring) | 3.37 GB/s | 1.25% | +3.0%
-| `bidirectional_lockless/1048576` | asio (coroutines, io_uring) | 3.28 GB/s | 1.49% | +0.2%
-| `bidirectional_lockless/1048576` | asio (callbacks, io_uring) | 3.27 GB/s | 1.11% | baseline (io_uring)
-| `bidirectional_lockless/16384` | corosio (io_uring) | 1.54 GB/s | 1.96% | -8.0%
-| `bidirectional_lockless/16384` | asio (coroutines, io_uring) | 1.66 GB/s | 1.10% | -0.5%
-| `bidirectional_lockless/16384` | asio (callbacks, io_uring) | 1.67 GB/s | 2.44% | baseline (io_uring)
-| `bidirectional_lockless/262144` | corosio (io_uring) | 3.25 GB/s | 1.02% | +13.0%
-| `bidirectional_lockless/262144` | asio (coroutines, io_uring) | 2.90 GB/s | 0.99% | +0.8%
-| `bidirectional_lockless/262144` | asio (callbacks, io_uring) | 2.88 GB/s | 0.46% | baseline (io_uring)
-| `bidirectional_lockless/4096` | corosio (io_uring) | 494.3 MB/s | 0.58% | -1.9%
-| `bidirectional_lockless/4096` | asio (coroutines, io_uring) | 494.6 MB/s | 0.28% | -1.8%
-| `bidirectional_lockless/4096` | asio (callbacks, io_uring) | 503.6 MB/s | 1.55% | baseline (io_uring)
-| `bidirectional_lockless/65536` | corosio (io_uring) | 2.78 GB/s | 0.90% | +5.1%
-| `bidirectional_lockless/65536` | asio (coroutines, io_uring) | 2.61 GB/s | 1.69% | -1.1%
-| `bidirectional_lockless/65536` | asio (callbacks, io_uring) | 2.64 GB/s | 2.18% | baseline (io_uring)
+| `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)
|===
====
@@ -940,15 +940,15 @@ image::bench/linux-socket_throughput-uring-g2.svg[socket throughput comparison (
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `multithread/2` | corosio (io_uring) | 3.67 GB/s | 1.05% | +123.3%
-| `multithread/2` | asio (coroutines, io_uring) | 1.75 GB/s | 7.63% | +6.8%
-| `multithread/2` | asio (callbacks, io_uring) | 1.64 GB/s | 7.69% | baseline (io_uring)
-| `multithread/4` | corosio (io_uring) | 5.08 GB/s | 0.33% | +206.1%
-| `multithread/4` | asio (coroutines, io_uring) | 1.64 GB/s | 0.65% | -1.2%
-| `multithread/4` | asio (callbacks, io_uring) | 1.66 GB/s | 0.65% | baseline (io_uring)
-| `multithread/8` | corosio (io_uring) | 5.13 GB/s | 0.17% | +214.9%
-| `multithread/8` | asio (coroutines, io_uring) | 1.61 GB/s | 0.94% | -1.0%
-| `multithread/8` | asio (callbacks, io_uring) | 1.63 GB/s | 0.60% | baseline (io_uring)
+| `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)
|===
====
@@ -964,42 +964,42 @@ image::bench/linux-socket_throughput-uring-g3.svg[socket throughput comparison (
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `unidirectional/1024` | corosio (io_uring) | 139.2 MB/s | 0.31% | +51.1%
-| `unidirectional/1024` | asio (coroutines, io_uring) | 90.70 MB/s | 0.50% | -1.6%
-| `unidirectional/1024` | asio (callbacks, io_uring) | 92.14 MB/s | 1.18% | baseline (io_uring)
-| `unidirectional/1048576` | corosio (io_uring) | 3.41 GB/s | 1.66% | +3.5%
-| `unidirectional/1048576` | asio (coroutines, io_uring) | 3.31 GB/s | 2.10% | +0.3%
-| `unidirectional/1048576` | asio (callbacks, io_uring) | 3.30 GB/s | 0.48% | baseline (io_uring)
-| `unidirectional/16384` | corosio (io_uring) | 1.54 GB/s | 3.75% | +16.9%
-| `unidirectional/16384` | asio (coroutines, io_uring) | 1.32 GB/s | 1.75% | -0.2%
-| `unidirectional/16384` | asio (callbacks, io_uring) | 1.32 GB/s | 1.06% | baseline (io_uring)
-| `unidirectional/262144` | corosio (io_uring) | 3.23 GB/s | 1.54% | +6.1%
-| `unidirectional/262144` | asio (coroutines, io_uring) | 3.07 GB/s | 1.19% | +1.0%
-| `unidirectional/262144` | asio (callbacks, io_uring) | 3.04 GB/s | 0.67% | baseline (io_uring)
-| `unidirectional/4096` | corosio (io_uring) | 491.5 MB/s | 1.27% | +36.5%
-| `unidirectional/4096` | asio (coroutines, io_uring) | 354.4 MB/s | 0.83% | -1.6%
-| `unidirectional/4096` | asio (callbacks, io_uring) | 360.0 MB/s | 0.52% | baseline (io_uring)
-| `unidirectional/65536` | corosio (io_uring) | 2.72 GB/s | 0.87% | +3.1%
-| `unidirectional/65536` | asio (coroutines, io_uring) | 2.64 GB/s | 2.73% | -0.2%
-| `unidirectional/65536` | asio (callbacks, io_uring) | 2.64 GB/s | 2.12% | baseline (io_uring)
-| `unidirectional_lockless/1024` | corosio (io_uring) | 139.7 MB/s | 0.91% | +49.0%
-| `unidirectional_lockless/1024` | asio (coroutines, io_uring) | 92.09 MB/s | 0.45% | -1.8%
-| `unidirectional_lockless/1024` | asio (callbacks, io_uring) | 93.74 MB/s | 1.32% | baseline (io_uring)
-| `unidirectional_lockless/1048576` | corosio (io_uring) | 3.34 GB/s | 1.53% | -4.7%
-| `unidirectional_lockless/1048576` | asio (coroutines, io_uring) | 3.52 GB/s | 0.43% | +0.5%
-| `unidirectional_lockless/1048576` | asio (callbacks, io_uring) | 3.51 GB/s | 0.76% | baseline (io_uring)
-| `unidirectional_lockless/16384` | corosio (io_uring) | 1.62 GB/s | 2.27% | +21.0%
-| `unidirectional_lockless/16384` | asio (coroutines, io_uring) | 1.33 GB/s | 1.46% | -0.6%
-| `unidirectional_lockless/16384` | asio (callbacks, io_uring) | 1.34 GB/s | 2.07% | baseline (io_uring)
-| `unidirectional_lockless/262144` | corosio (io_uring) | 3.23 GB/s | 1.21% | +6.8%
-| `unidirectional_lockless/262144` | asio (coroutines, io_uring) | 3.10 GB/s | 1.13% | +2.2%
-| `unidirectional_lockless/262144` | asio (callbacks, io_uring) | 3.03 GB/s | 1.03% | baseline (io_uring)
-| `unidirectional_lockless/4096` | corosio (io_uring) | 494.4 MB/s | 0.99% | +35.3%
-| `unidirectional_lockless/4096` | asio (coroutines, io_uring) | 361.0 MB/s | 0.29% | -1.2%
-| `unidirectional_lockless/4096` | asio (callbacks, io_uring) | 365.4 MB/s | 1.55% | baseline (io_uring)
-| `unidirectional_lockless/65536` | corosio (io_uring) | 2.73 GB/s | 2.34% | +1.8%
-| `unidirectional_lockless/65536` | asio (coroutines, io_uring) | 2.64 GB/s | 2.13% | -1.4%
-| `unidirectional_lockless/65536` | asio (callbacks, io_uring) | 2.68 GB/s | 2.22% | baseline (io_uring)
+| `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)
|===
====
@@ -1017,42 +1017,42 @@ image::bench/linux-socket_throughput-epoll-g1.svg[socket throughput comparison (
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `bidirectional/1024` | corosio (epoll) | 134.2 MB/s | 0.37% | -3.7%
-| `bidirectional/1024` | asio (coroutines, epoll) | 134.9 MB/s | 0.79% | -3.2%
-| `bidirectional/1024` | asio (callbacks, epoll) | 139.4 MB/s | 0.93% | baseline (epoll)
-| `bidirectional/1048576` | corosio (epoll) | 3.24 GB/s | 2.03% | -1.1%
-| `bidirectional/1048576` | asio (coroutines, epoll) | 3.26 GB/s | 1.14% | -0.7%
-| `bidirectional/1048576` | asio (callbacks, epoll) | 3.28 GB/s | 0.90% | baseline (epoll)
-| `bidirectional/16384` | corosio (epoll) | 1.64 GB/s | 0.44% | -1.8%
-| `bidirectional/16384` | asio (coroutines, epoll) | 1.63 GB/s | 1.71% | -2.4%
-| `bidirectional/16384` | asio (callbacks, epoll) | 1.67 GB/s | 1.45% | baseline (epoll)
-| `bidirectional/262144` | corosio (epoll) | 3.23 GB/s | 0.81% | +12.5%
-| `bidirectional/262144` | asio (coroutines, epoll) | 2.92 GB/s | 2.11% | +1.7%
-| `bidirectional/262144` | asio (callbacks, epoll) | 2.87 GB/s | 0.66% | baseline (epoll)
-| `bidirectional/4096` | corosio (epoll) | 506.4 MB/s | 0.56% | +1.1%
-| `bidirectional/4096` | asio (coroutines, epoll) | 491.0 MB/s | 1.43% | -2.0%
-| `bidirectional/4096` | asio (callbacks, epoll) | 500.9 MB/s | 1.38% | baseline (epoll)
-| `bidirectional/65536` | corosio (epoll) | 2.57 GB/s | 2.19% | -2.4%
-| `bidirectional/65536` | asio (coroutines, epoll) | 2.59 GB/s | 1.89% | -1.4%
-| `bidirectional/65536` | asio (callbacks, epoll) | 2.63 GB/s | 1.51% | baseline (epoll)
-| `bidirectional_lockless/1024` | corosio (epoll) | 135.0 MB/s | 1.20% | -4.5%
-| `bidirectional_lockless/1024` | asio (coroutines, epoll) | 137.6 MB/s | 1.28% | -2.7%
-| `bidirectional_lockless/1024` | asio (callbacks, epoll) | 141.4 MB/s | 0.91% | baseline (epoll)
-| `bidirectional_lockless/1048576` | corosio (epoll) | 3.25 GB/s | 2.77% | -2.2%
-| `bidirectional_lockless/1048576` | asio (coroutines, epoll) | 3.27 GB/s | 0.87% | -1.6%
-| `bidirectional_lockless/1048576` | asio (callbacks, epoll) | 3.33 GB/s | 1.88% | baseline (epoll)
-| `bidirectional_lockless/16384` | corosio (epoll) | 1.65 GB/s | 0.29% | -2.4%
-| `bidirectional_lockless/16384` | asio (coroutines, epoll) | 1.67 GB/s | 0.77% | -1.4%
-| `bidirectional_lockless/16384` | asio (callbacks, epoll) | 1.69 GB/s | 1.75% | baseline (epoll)
-| `bidirectional_lockless/262144` | corosio (epoll) | 3.23 GB/s | 1.02% | +10.0%
-| `bidirectional_lockless/262144` | asio (coroutines, epoll) | 2.86 GB/s | 1.38% | -2.5%
-| `bidirectional_lockless/262144` | asio (callbacks, epoll) | 2.93 GB/s | 2.33% | baseline (epoll)
-| `bidirectional_lockless/4096` | corosio (epoll) | 510.0 MB/s | 1.42% | -0.2%
-| `bidirectional_lockless/4096` | asio (coroutines, epoll) | 496.9 MB/s | 1.06% | -2.8%
-| `bidirectional_lockless/4096` | asio (callbacks, epoll) | 511.1 MB/s | 1.13% | baseline (epoll)
-| `bidirectional_lockless/65536` | corosio (epoll) | 2.52 GB/s | 3.26% | -5.2%
-| `bidirectional_lockless/65536` | asio (coroutines, epoll) | 2.60 GB/s | 2.95% | -2.4%
-| `bidirectional_lockless/65536` | asio (callbacks, epoll) | 2.66 GB/s | 2.19% | baseline (epoll)
+| `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)
|===
====
@@ -1068,15 +1068,15 @@ image::bench/linux-socket_throughput-epoll-g2.svg[socket throughput comparison (
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `multithread/2` | corosio (epoll) | 3.40 GB/s | 0.78% | +44.6%
-| `multithread/2` | asio (coroutines, epoll) | 2.28 GB/s | 2.00% | -2.9%
-| `multithread/2` | asio (callbacks, epoll) | 2.35 GB/s | 1.70% | baseline (epoll)
-| `multithread/4` | corosio (epoll) | 4.87 GB/s | 0.44% | +38.0%
-| `multithread/4` | asio (coroutines, epoll) | 3.53 GB/s | 0.56% | +0.1%
-| `multithread/4` | asio (callbacks, epoll) | 3.53 GB/s | 0.57% | baseline (epoll)
-| `multithread/8` | corosio (epoll) | 4.95 GB/s | 0.22% | +25.4%
-| `multithread/8` | asio (coroutines, epoll) | 3.94 GB/s | 0.19% | -0.3%
-| `multithread/8` | asio (callbacks, epoll) | 3.95 GB/s | 0.35% | baseline (epoll)
+| `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)
|===
====
@@ -1092,42 +1092,42 @@ image::bench/linux-socket_throughput-epoll-g3.svg[socket throughput comparison (
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `unidirectional/1024` | corosio (epoll) | 126.1 MB/s | 1.10% | +34.6%
-| `unidirectional/1024` | asio (coroutines, epoll) | 91.85 MB/s | 0.45% | -1.9%
-| `unidirectional/1024` | asio (callbacks, epoll) | 93.66 MB/s | 0.88% | baseline (epoll)
-| `unidirectional/1048576` | corosio (epoll) | 3.38 GB/s | 0.96% | -0.7%
-| `unidirectional/1048576` | asio (coroutines, epoll) | 3.36 GB/s | 2.04% | -1.3%
-| `unidirectional/1048576` | asio (callbacks, epoll) | 3.40 GB/s | 0.40% | baseline (epoll)
-| `unidirectional/16384` | corosio (epoll) | 1.58 GB/s | 1.29% | +15.6%
-| `unidirectional/16384` | asio (coroutines, epoll) | 1.33 GB/s | 1.39% | -3.0%
-| `unidirectional/16384` | asio (callbacks, epoll) | 1.37 GB/s | 1.28% | baseline (epoll)
-| `unidirectional/262144` | corosio (epoll) | 3.35 GB/s | 1.21% | +10.0%
-| `unidirectional/262144` | asio (coroutines, epoll) | 3.04 GB/s | 1.49% | -0.2%
-| `unidirectional/262144` | asio (callbacks, epoll) | 3.04 GB/s | 2.22% | baseline (epoll)
-| `unidirectional/4096` | corosio (epoll) | 477.0 MB/s | 1.07% | +30.0%
-| `unidirectional/4096` | asio (coroutines, epoll) | 358.2 MB/s | 0.83% | -2.4%
-| `unidirectional/4096` | asio (callbacks, epoll) | 366.8 MB/s | 0.70% | baseline (epoll)
-| `unidirectional/65536` | corosio (epoll) | 2.76 GB/s | 3.74% | +2.4%
-| `unidirectional/65536` | asio (coroutines, epoll) | 2.69 GB/s | 1.14% | -0.3%
-| `unidirectional/65536` | asio (callbacks, epoll) | 2.70 GB/s | 2.02% | baseline (epoll)
-| `unidirectional_lockless/1024` | corosio (epoll) | 126.1 MB/s | 0.80% | +33.3%
-| `unidirectional_lockless/1024` | asio (coroutines, epoll) | 93.22 MB/s | 1.39% | -1.5%
-| `unidirectional_lockless/1024` | asio (callbacks, epoll) | 94.59 MB/s | 0.33% | baseline (epoll)
-| `unidirectional_lockless/1048576` | corosio (epoll) | 3.35 GB/s | 1.22% | -6.3%
-| `unidirectional_lockless/1048576` | asio (coroutines, epoll) | 3.55 GB/s | 2.34% | -0.8%
-| `unidirectional_lockless/1048576` | asio (callbacks, epoll) | 3.57 GB/s | 1.29% | baseline (epoll)
-| `unidirectional_lockless/16384` | corosio (epoll) | 1.56 GB/s | 2.38% | +13.6%
-| `unidirectional_lockless/16384` | asio (coroutines, epoll) | 1.35 GB/s | 1.63% | -2.0%
-| `unidirectional_lockless/16384` | asio (callbacks, epoll) | 1.37 GB/s | 1.51% | baseline (epoll)
-| `unidirectional_lockless/262144` | corosio (epoll) | 3.35 GB/s | 1.59% | +7.5%
-| `unidirectional_lockless/262144` | asio (coroutines, epoll) | 3.07 GB/s | 1.21% | -1.4%
-| `unidirectional_lockless/262144` | asio (callbacks, epoll) | 3.11 GB/s | 1.77% | baseline (epoll)
-| `unidirectional_lockless/4096` | corosio (epoll) | 476.5 MB/s | 1.12% | +28.4%
-| `unidirectional_lockless/4096` | asio (coroutines, epoll) | 364.4 MB/s | 1.20% | -1.8%
-| `unidirectional_lockless/4096` | asio (callbacks, epoll) | 371.0 MB/s | 0.39% | baseline (epoll)
-| `unidirectional_lockless/65536` | corosio (epoll) | 2.74 GB/s | 4.50% | +0.3%
-| `unidirectional_lockless/65536` | asio (coroutines, epoll) | 2.73 GB/s | 2.28% | +0.1%
-| `unidirectional_lockless/65536` | asio (callbacks, epoll) | 2.73 GB/s | 2.83% | baseline (epoll)
+| `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)
|===
====
diff --git a/doc/modules/ROOT/pages/benchmarks/macos.adoc b/doc/modules/ROOT/pages/benchmarks/macos.adoc
index 1b6051c73..0ed886a5a 100644
--- a/doc/modules/ROOT/pages/benchmarks/macos.adoc
+++ b/doc/modules/ROOT/pages/benchmarks/macos.adoc
@@ -2,13 +2,13 @@
:page-mode: explanation
:toc: left
-_Generated 2026-10-02 from corosio `e2de06fda069` — https://github.com/cppalliance/corosio/actions/runs/37015995763[benchmark run]. This page is fully generated; do not edit by hand (see the xref:benchmarks/index.adoc[Benchmarks landing page])._
+_Generated 2026-11-06 from corosio `0b3830d5c30b` — https://github.com/cppalliance/corosio/actions/runs/42119198783[benchmark run]. This page is fully generated; do not edit by hand (see the xref:benchmarks/index.adoc[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 xref:benchmarks/index.adoc[Methodology] for how these figures are computed.
-**68 faster · 15 within noise · 30 slower** of 113 benchmarks — median **+58.8%** vs Boost.Asio (callbacks) on the same reactor.
+**70 faster · 26 within noise · 17 slower** of 113 benchmarks — median **+62.7%** vs Boost.Asio (callbacks) on the same reactor.
image::bench/macos-summary.svg[summary,role=bch-block,opts=inline]
@@ -24,13 +24,13 @@ image::bench/macos-summary.svg[summary,role=bch-block,opts=inline]
| Compiler | Apple clang version 17.0.0 (clang-1700.6.3.2)
| CMake | `cmake version 4.4.3`
| liburing | n/a
-| Boost commit | 39fa1e9a3491bd099b570935b3f3422065f91b03
-| Asio commit | a7dc25b4cb6c49a6946d86ea20664f1027203225
+| Boost commit | b6d874b77b75085a1b35c640a76d37ab8cd9bb97
+| Asio commit | e99d9da6d9b76a222e29dcaf3d2df51c788b7527
| Asio reactor | kqueue
-| Capy commit | a372a6b054261f29497ac0d19c2a9533f9eaad40
-| Corosio commit | e2de06fda069607f34bc957cbefcbd9ba12fddca
-| Corosio branch | pr/benchmark-report
-| Date (UTC) | 2026-10-02
+| Capy commit | bdadc6adef8c8eb79da6454373175bb1428be524
+| Corosio commit | 0b3830d5c30b96e4a95c0248953575ba7ffcd4d1
+| Corosio branch | develop
+| Date (UTC) | 2026-11-05
| Iterations | 7
| Duration per benchmark (s) | 2.0
|===
@@ -51,33 +51,33 @@ image::bench/macos-accept_churn.svg[accept churn comparison,role=bch-block,opts=
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `burst/10` | corosio (kqueue) | 4.12K ops/s | 4.19% | -10.2%
-| `burst/10` | asio (coroutines) | 3.18K ops/s | 1.54% | -30.6%
-| `burst/10` | asio (callbacks) | 4.58K ops/s | 2.22% | baseline
-| `burst/100` | corosio (kqueue) | 426.7 ops/s | 4.25% | -27.3%
-| `burst/100` | asio (coroutines) | 343.8 ops/s | 2.96% | -41.4%
-| `burst/100` | asio (callbacks) | 587.1 ops/s | 12.84% | baseline
-| `burst_lockless/10` | corosio (kqueue) | 4.11K ops/s | 3.92% | -10.5%
-| `burst_lockless/10` | asio (coroutines) | 3.24K ops/s | 1.91% | -29.4%
-| `burst_lockless/10` | asio (callbacks) | 4.59K ops/s | 9.95% | baseline
-| `burst_lockless/100` | corosio (kqueue) | 424.0 ops/s | 3.50% | -28.0%
-| `burst_lockless/100` | asio (coroutines) | 347.1 ops/s | 2.79% | -41.0%
-| `burst_lockless/100` | asio (callbacks) | 588.5 ops/s | 4.01% | baseline
-| `concurrent/1` | corosio (kqueue) | 19.67K ops/s | 0.52% | +9.7%
-| `concurrent/1` | asio (coroutines) | 17.79K ops/s | 1.75% | -0.7%
-| `concurrent/1` | asio (callbacks) | 17.93K ops/s | 0.74% | baseline
-| `concurrent/16` | corosio (kqueue) | 34.00K ops/s | 3.18% | -20.6%
-| `concurrent/16` | asio (coroutines) | 42.53K ops/s | 2.55% | -0.7%
-| `concurrent/16` | asio (callbacks) | 42.81K ops/s | 6.50% | baseline
-| `concurrent/4` | corosio (kqueue) | 28.71K ops/s | 2.41% | -8.2%
-| `concurrent/4` | asio (coroutines) | 30.05K ops/s | 1.48% | -3.9%
-| `concurrent/4` | asio (callbacks) | 31.27K ops/s | 3.26% | baseline
-| `sequential` | corosio (kqueue) | 19.68K ops/s | 0.50% | +9.1%
-| `sequential` | asio (coroutines) | 17.81K ops/s | 0.97% | -1.3%
-| `sequential` | asio (callbacks) | 18.05K ops/s | 0.54% | baseline
-| `sequential_lockless` | corosio (kqueue) | 19.73K ops/s | 1.83% | +9.8%
-| `sequential_lockless` | asio (coroutines) | 17.79K ops/s | 1.50% | -1.0%
-| `sequential_lockless` | asio (callbacks) | 17.97K ops/s | 0.50% | baseline
+| `burst/10` | corosio (kqueue) | 4.57K ops/s | 5.09% | -4.0%
+| `burst/10` | asio (coroutines) | 3.17K ops/s | 1.30% | -33.4%
+| `burst/10` | asio (callbacks) | 4.76K ops/s | 5.89% | baseline
+| `burst/100` | corosio (kqueue) | 443.2 ops/s | 5.77% | -23.1%
+| `burst/100` | asio (coroutines) | 353.4 ops/s | 2.61% | -38.7%
+| `burst/100` | asio (callbacks) | 576.7 ops/s | 14.07% | baseline
+| `burst_lockless/10` | corosio (kqueue) | 4.39K ops/s | 7.28% | -4.1%
+| `burst_lockless/10` | asio (coroutines) | 3.21K ops/s | 2.47% | -29.9%
+| `burst_lockless/10` | asio (callbacks) | 4.58K ops/s | 8.74% | baseline
+| `burst_lockless/100` | corosio (kqueue) | 454.1 ops/s | 5.71% | -14.8%
+| `burst_lockless/100` | asio (coroutines) | 340.4 ops/s | 4.85% | -36.1%
+| `burst_lockless/100` | asio (callbacks) | 532.7 ops/s | 21.18% | baseline
+| `concurrent/1` | corosio (kqueue) | 20.69K ops/s | 0.72% | +15.5%
+| `concurrent/1` | asio (coroutines) | 17.69K ops/s | 1.06% | -1.2%
+| `concurrent/1` | asio (callbacks) | 17.91K ops/s | 1.00% | baseline
+| `concurrent/16` | corosio (kqueue) | 35.88K ops/s | 4.40% | -13.0%
+| `concurrent/16` | asio (coroutines) | 41.34K ops/s | 2.30% | +0.2%
+| `concurrent/16` | asio (callbacks) | 41.23K ops/s | 7.59% | baseline
+| `concurrent/4` | corosio (kqueue) | 28.87K ops/s | 0.31% | -6.5%
+| `concurrent/4` | asio (coroutines) | 29.94K ops/s | 3.00% | -3.0%
+| `concurrent/4` | asio (callbacks) | 30.86K ops/s | 1.08% | baseline
+| `sequential` | corosio (kqueue) | 20.84K ops/s | 0.68% | +15.1%
+| `sequential` | asio (coroutines) | 17.93K ops/s | 0.81% | -1.0%
+| `sequential` | asio (callbacks) | 18.11K ops/s | 0.62% | baseline
+| `sequential_lockless` | corosio (kqueue) | 20.69K ops/s | 1.01% | +16.2%
+| `sequential_lockless` | asio (coroutines) | 17.73K ops/s | 1.00% | -0.4%
+| `sequential_lockless` | asio (callbacks) | 17.80K ops/s | 0.66% | baseline
|===
====
@@ -101,24 +101,24 @@ image::bench/macos-fan_out-g1.svg[fan out comparison, part 1,role=bch-block,opts
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `concurrent_parents/1` | corosio (kqueue) | 7.72K ops/s | 0.42% | -4.7%
-| `concurrent_parents/1` | asio (coroutines) | 7.20K ops/s | 0.22% | -11.1%
-| `concurrent_parents/1` | asio (callbacks) | 8.10K ops/s | 0.65% | baseline
-| `concurrent_parents/16` | corosio (kqueue) | 8.45K ops/s | 19.25% | -7.3%
-| `concurrent_parents/16` | asio (coroutines) | 6.35K ops/s | 19.09% | -30.3%
-| `concurrent_parents/16` | asio (callbacks) | 9.11K ops/s | 17.43% | baseline
-| `concurrent_parents/4` | corosio (kqueue) | 8.25K ops/s | 1.64% | -7.8%
-| `concurrent_parents/4` | asio (coroutines) | 8.47K ops/s | 0.83% | -5.4%
-| `concurrent_parents/4` | asio (callbacks) | 8.95K ops/s | 0.17% | baseline
-| `concurrent_parents_lockless/1` | corosio (kqueue) | 7.76K ops/s | 0.94% | -4.8%
-| `concurrent_parents_lockless/1` | asio (coroutines) | 7.25K ops/s | 0.21% | -11.1%
-| `concurrent_parents_lockless/1` | asio (callbacks) | 8.16K ops/s | 0.69% | baseline
-| `concurrent_parents_lockless/16` | corosio (kqueue) | 8.29K ops/s | 14.13% | -10.3%
-| `concurrent_parents_lockless/16` | asio (coroutines) | 6.34K ops/s | 18.94% | -31.4%
-| `concurrent_parents_lockless/16` | asio (callbacks) | 9.24K ops/s | 10.75% | baseline
-| `concurrent_parents_lockless/4` | corosio (kqueue) | 8.10K ops/s | 1.89% | -10.5%
-| `concurrent_parents_lockless/4` | asio (coroutines) | 8.65K ops/s | 0.83% | -4.4%
-| `concurrent_parents_lockless/4` | asio (callbacks) | 9.05K ops/s | 0.31% | baseline
+| `concurrent_parents/1` | corosio (kqueue) | 8.07K ops/s | 1.20% | +0.3%
+| `concurrent_parents/1` | asio (coroutines) | 7.27K ops/s | 0.41% | -9.7%
+| `concurrent_parents/1` | asio (callbacks) | 8.04K ops/s | 0.60% | baseline
+| `concurrent_parents/16` | corosio (kqueue) | 6.25K ops/s | 19.09% | -31.7%
+| `concurrent_parents/16` | asio (coroutines) | 8.87K ops/s | 16.27% | -2.9%
+| `concurrent_parents/16` | asio (callbacks) | 9.14K ops/s | 20.19% | baseline
+| `concurrent_parents/4` | corosio (kqueue) | 8.29K ops/s | 1.28% | -7.8%
+| `concurrent_parents/4` | asio (coroutines) | 8.58K ops/s | 0.72% | -4.6%
+| `concurrent_parents/4` | asio (callbacks) | 8.99K ops/s | 0.31% | baseline
+| `concurrent_parents_lockless/1` | corosio (kqueue) | 8.15K ops/s | 1.59% | -0.3%
+| `concurrent_parents_lockless/1` | asio (coroutines) | 7.32K ops/s | 0.44% | -10.5%
+| `concurrent_parents_lockless/1` | asio (callbacks) | 8.18K ops/s | 0.53% | baseline
+| `concurrent_parents_lockless/16` | corosio (kqueue) | 6.06K ops/s | 19.10% | -6.4%
+| `concurrent_parents_lockless/16` | asio (coroutines) | 8.86K ops/s | 16.56% | +36.8%
+| `concurrent_parents_lockless/16` | asio (callbacks) | 6.48K ops/s | 20.88% | baseline
+| `concurrent_parents_lockless/4` | corosio (kqueue) | 8.38K ops/s | 1.60% | -7.6%
+| `concurrent_parents_lockless/4` | asio (coroutines) | 8.68K ops/s | 0.65% | -4.4%
+| `concurrent_parents_lockless/4` | asio (callbacks) | 9.07K ops/s | 0.82% | baseline
|===
====
@@ -134,42 +134,42 @@ image::bench/macos-fan_out-g2.svg[fan out comparison, part 2,role=bch-block,opts
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `fork_join/1` | corosio (kqueue) | 46.39K ops/s | 0.98% | -23.4%
-| `fork_join/1` | asio (coroutines) | 29.26K ops/s | 1.31% | -51.7%
-| `fork_join/1` | asio (callbacks) | 60.56K ops/s | 1.56% | baseline
-| `fork_join/16` | corosio (kqueue) | 7.70K ops/s | 0.41% | -4.1%
-| `fork_join/16` | asio (coroutines) | 7.21K ops/s | 0.18% | -10.2%
-| `fork_join/16` | asio (callbacks) | 8.03K ops/s | 0.70% | baseline
-| `fork_join/4` | corosio (kqueue) | 21.70K ops/s | 0.41% | -6.7%
-| `fork_join/4` | asio (coroutines) | 16.80K ops/s | 0.33% | -27.8%
-| `fork_join/4` | asio (callbacks) | 23.27K ops/s | 0.31% | baseline
-| `fork_join/64` | corosio (kqueue) | 1.99K ops/s | 2.25% | -11.2%
-| `fork_join/64` | asio (coroutines) | 2.08K ops/s | 0.97% | -7.4%
-| `fork_join/64` | asio (callbacks) | 2.25K ops/s | 0.16% | baseline
-| `fork_join_lockless/1` | corosio (kqueue) | 46.88K ops/s | 0.48% | -26.6%
-| `fork_join_lockless/1` | asio (coroutines) | 29.74K ops/s | 0.48% | -53.4%
-| `fork_join_lockless/1` | asio (callbacks) | 63.85K ops/s | 0.50% | baseline
-| `fork_join_lockless/16` | corosio (kqueue) | 7.80K ops/s | 0.71% | -4.3%
-| `fork_join_lockless/16` | asio (coroutines) | 7.27K ops/s | 0.24% | -10.8%
-| `fork_join_lockless/16` | asio (callbacks) | 8.15K ops/s | 0.69% | baseline
-| `fork_join_lockless/4` | corosio (kqueue) | 21.77K ops/s | 0.50% | -7.2%
-| `fork_join_lockless/4` | asio (coroutines) | 16.89K ops/s | 0.22% | -28.0%
-| `fork_join_lockless/4` | asio (callbacks) | 23.47K ops/s | 0.19% | baseline
-| `fork_join_lockless/64` | corosio (kqueue) | 2.08K ops/s | 2.38% | -8.5%
-| `fork_join_lockless/64` | asio (coroutines) | 2.10K ops/s | 1.02% | -7.4%
-| `fork_join_lockless/64` | asio (callbacks) | 2.27K ops/s | 0.13% | baseline
-| `nested/16` | corosio (kqueue) | 2.04K ops/s | 1.78% | -8.9%
-| `nested/16` | asio (coroutines) | 2.01K ops/s | 0.50% | -10.2%
-| `nested/16` | asio (callbacks) | 2.24K ops/s | 0.29% | baseline
-| `nested/4` | corosio (kqueue) | 7.07K ops/s | 0.18% | -12.5%
-| `nested/4` | asio (coroutines) | 6.49K ops/s | 0.25% | -19.7%
-| `nested/4` | asio (callbacks) | 8.08K ops/s | 0.84% | baseline
-| `nested_lockless/16` | corosio (kqueue) | 2.00K ops/s | 2.14% | -11.6%
-| `nested_lockless/16` | asio (coroutines) | 2.03K ops/s | 0.73% | -10.4%
-| `nested_lockless/16` | asio (callbacks) | 2.26K ops/s | 0.25% | baseline
-| `nested_lockless/4` | corosio (kqueue) | 7.19K ops/s | 0.41% | -11.8%
-| `nested_lockless/4` | asio (coroutines) | 6.56K ops/s | 0.32% | -19.5%
-| `nested_lockless/4` | asio (callbacks) | 8.15K ops/s | 0.69% | baseline
+| `fork_join/1` | corosio (kqueue) | 49.70K ops/s | 0.65% | -18.2%
+| `fork_join/1` | asio (coroutines) | 29.41K ops/s | 0.77% | -51.6%
+| `fork_join/1` | asio (callbacks) | 60.76K ops/s | 0.89% | baseline
+| `fork_join/16` | corosio (kqueue) | 8.08K ops/s | 1.26% | -0.5%
+| `fork_join/16` | asio (coroutines) | 7.27K ops/s | 0.33% | -10.5%
+| `fork_join/16` | asio (callbacks) | 8.12K ops/s | 0.77% | baseline
+| `fork_join/4` | corosio (kqueue) | 23.54K ops/s | 0.77% | +0.6%
+| `fork_join/4` | asio (coroutines) | 16.87K ops/s | 0.14% | -27.9%
+| `fork_join/4` | asio (callbacks) | 23.40K ops/s | 0.13% | baseline
+| `fork_join/64` | corosio (kqueue) | 2.08K ops/s | 1.67% | -7.7%
+| `fork_join/64` | asio (coroutines) | 2.15K ops/s | 1.35% | -4.8%
+| `fork_join/64` | asio (callbacks) | 2.26K ops/s | 0.28% | baseline
+| `fork_join_lockless/1` | corosio (kqueue) | 50.35K ops/s | 0.21% | -21.7%
+| `fork_join_lockless/1` | asio (coroutines) | 29.81K ops/s | 0.35% | -53.6%
+| `fork_join_lockless/1` | asio (callbacks) | 64.31K ops/s | 0.52% | baseline
+| `fork_join_lockless/16` | corosio (kqueue) | 8.16K ops/s | 1.29% | -0.3%
+| `fork_join_lockless/16` | asio (coroutines) | 7.31K ops/s | 0.34% | -10.7%
+| `fork_join_lockless/16` | asio (callbacks) | 8.19K ops/s | 0.66% | baseline
+| `fork_join_lockless/4` | corosio (kqueue) | 23.74K ops/s | 1.11% | +0.6%
+| `fork_join_lockless/4` | asio (coroutines) | 16.95K ops/s | 0.30% | -28.2%
+| `fork_join_lockless/4` | asio (callbacks) | 23.59K ops/s | 0.31% | baseline
+| `fork_join_lockless/64` | corosio (kqueue) | 2.10K ops/s | 1.68% | -7.9%
+| `fork_join_lockless/64` | asio (coroutines) | 2.13K ops/s | 1.55% | -6.7%
+| `fork_join_lockless/64` | asio (callbacks) | 2.28K ops/s | 0.65% | baseline
+| `nested/16` | corosio (kqueue) | 2.05K ops/s | 1.54% | -8.8%
+| `nested/16` | asio (coroutines) | 2.03K ops/s | 0.64% | -9.6%
+| `nested/16` | asio (callbacks) | 2.25K ops/s | 0.44% | baseline
+| `nested/4` | corosio (kqueue) | 8.00K ops/s | 1.20% | -0.2%
+| `nested/4` | asio (coroutines) | 6.57K ops/s | 0.56% | -18.1%
+| `nested/4` | asio (callbacks) | 8.02K ops/s | 0.65% | baseline
+| `nested_lockless/16` | corosio (kqueue) | 2.07K ops/s | 1.56% | -9.2%
+| `nested_lockless/16` | asio (coroutines) | 2.05K ops/s | 0.75% | -10.1%
+| `nested_lockless/16` | asio (callbacks) | 2.28K ops/s | 0.38% | baseline
+| `nested_lockless/4` | corosio (kqueue) | 8.06K ops/s | 1.13% | -0.7%
+| `nested_lockless/4` | asio (coroutines) | 6.67K ops/s | 0.80% | -17.7%
+| `nested_lockless/4` | asio (callbacks) | 8.11K ops/s | 0.66% | baseline
|===
====
@@ -193,39 +193,39 @@ image::bench/macos-http_server.svg[http server comparison,role=bch-block,opts=in
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `concurrent/1` | corosio (kqueue) | 49.55K ops/s | 0.29% | -17.9%
-| `concurrent/1` | asio (coroutines) | 57.16K ops/s | 1.17% | -5.3%
-| `concurrent/1` | asio (callbacks) | 60.35K ops/s | 0.94% | baseline
-| `concurrent/16` | corosio (kqueue) | 126.9K ops/s | 0.37% | -0.2%
-| `concurrent/16` | asio (coroutines) | 126.8K ops/s | 0.63% | -0.3%
-| `concurrent/16` | asio (callbacks) | 127.2K ops/s | 0.41% | baseline
-| `concurrent/32` | corosio (kqueue) | 127.9K ops/s | 0.92% | -8.4%
-| `concurrent/32` | asio (coroutines) | 135.2K ops/s | 0.21% | -3.1%
-| `concurrent/32` | asio (callbacks) | 139.6K ops/s | 0.44% | baseline
-| `concurrent/4` | corosio (kqueue) | 88.07K ops/s | 0.45% | -4.5%
-| `concurrent/4` | asio (coroutines) | 91.01K ops/s | 0.16% | -1.3%
-| `concurrent/4` | asio (callbacks) | 92.17K ops/s | 0.35% | baseline
-| `multithread/1` | corosio (kqueue) | 127.5K ops/s | 0.90% | -8.6%
-| `multithread/1` | asio (coroutines) | 134.9K ops/s | 0.18% | -3.3%
-| `multithread/1` | asio (callbacks) | 139.5K ops/s | 0.43% | baseline
-| `multithread/16` | corosio (kqueue) | 126.8K ops/s | 0.72% | +9.8%
-| `multithread/16` | asio (coroutines) | 114.2K ops/s | 0.49% | -1.1%
-| `multithread/16` | asio (callbacks) | 115.5K ops/s | 1.09% | baseline
-| `multithread/2` | corosio (kqueue) | 174.1K ops/s | 1.89% | +2.7%
-| `multithread/2` | asio (coroutines) | 167.9K ops/s | 0.20% | -1.0%
-| `multithread/2` | asio (callbacks) | 169.5K ops/s | 0.13% | baseline
-| `multithread/4` | corosio (kqueue) | 162.0K ops/s | 1.02% | +11.7%
-| `multithread/4` | asio (coroutines) | 143.3K ops/s | 0.19% | -1.2%
-| `multithread/4` | asio (callbacks) | 145.0K ops/s | 0.21% | baseline
-| `multithread/8` | corosio (kqueue) | 132.4K ops/s | 1.15% | +0.1%
-| `multithread/8` | asio (coroutines) | 128.8K ops/s | 0.57% | -2.6%
-| `multithread/8` | asio (callbacks) | 132.2K ops/s | 0.55% | baseline
-| `single_conn` | corosio (kqueue) | 49.49K ops/s | 0.20% | -18.2%
-| `single_conn` | asio (coroutines) | 56.88K ops/s | 0.89% | -6.0%
-| `single_conn` | asio (callbacks) | 60.49K ops/s | 0.80% | baseline
-| `single_conn_lockless` | corosio (kqueue) | 49.61K ops/s | 0.34% | -21.0%
-| `single_conn_lockless` | asio (coroutines) | 60.26K ops/s | 1.28% | -4.1%
-| `single_conn_lockless` | asio (callbacks) | 62.82K ops/s | 0.70% | baseline
+| `concurrent/1` | corosio (kqueue) | 49.69K ops/s | 0.35% | -19.6%
+| `concurrent/1` | asio (coroutines) | 58.60K ops/s | 0.76% | -5.1%
+| `concurrent/1` | asio (callbacks) | 61.77K ops/s | 0.88% | baseline
+| `concurrent/16` | corosio (kqueue) | 130.7K ops/s | 1.41% | +2.4%
+| `concurrent/16` | asio (coroutines) | 127.2K ops/s | 0.79% | -0.3%
+| `concurrent/16` | asio (callbacks) | 127.6K ops/s | 0.55% | baseline
+| `concurrent/32` | corosio (kqueue) | 128.4K ops/s | 1.61% | -8.4%
+| `concurrent/32` | asio (coroutines) | 136.6K ops/s | 0.36% | -2.5%
+| `concurrent/32` | asio (callbacks) | 140.1K ops/s | 0.53% | baseline
+| `concurrent/4` | corosio (kqueue) | 89.93K ops/s | 1.03% | -2.5%
+| `concurrent/4` | asio (coroutines) | 91.33K ops/s | 0.24% | -1.0%
+| `concurrent/4` | asio (callbacks) | 92.27K ops/s | 0.13% | baseline
+| `multithread/1` | corosio (kqueue) | 128.6K ops/s | 1.71% | -8.0%
+| `multithread/1` | asio (coroutines) | 136.5K ops/s | 0.30% | -2.4%
+| `multithread/1` | asio (callbacks) | 139.8K ops/s | 0.61% | baseline
+| `multithread/16` | corosio (kqueue) | 133.2K ops/s | 0.70% | +16.3%
+| `multithread/16` | asio (coroutines) | 114.1K ops/s | 1.23% | -0.4%
+| `multithread/16` | asio (callbacks) | 114.5K ops/s | 1.35% | baseline
+| `multithread/2` | corosio (kqueue) | 184.4K ops/s | 0.56% | +8.7%
+| `multithread/2` | asio (coroutines) | 168.7K ops/s | 0.11% | -0.6%
+| `multithread/2` | asio (callbacks) | 169.7K ops/s | 0.26% | baseline
+| `multithread/4` | corosio (kqueue) | 161.9K ops/s | 0.42% | +11.6%
+| `multithread/4` | asio (coroutines) | 143.5K ops/s | 0.25% | -1.1%
+| `multithread/4` | asio (callbacks) | 145.0K ops/s | 0.19% | baseline
+| `multithread/8` | corosio (kqueue) | 139.3K ops/s | 1.25% | +5.2%
+| `multithread/8` | asio (coroutines) | 130.1K ops/s | 0.70% | -1.7%
+| `multithread/8` | asio (callbacks) | 132.4K ops/s | 0.56% | baseline
+| `single_conn` | corosio (kqueue) | 49.58K ops/s | 0.25% | -19.8%
+| `single_conn` | asio (coroutines) | 58.38K ops/s | 1.16% | -5.6%
+| `single_conn` | asio (callbacks) | 61.83K ops/s | 0.97% | baseline
+| `single_conn_lockless` | corosio (kqueue) | 50.16K ops/s | 0.60% | -21.0%
+| `single_conn_lockless` | asio (coroutines) | 61.07K ops/s | 1.24% | -3.8%
+| `single_conn_lockless` | asio (callbacks) | 63.46K ops/s | 1.12% | baseline
|===
====
@@ -249,42 +249,42 @@ image::bench/macos-local_socket_latency.svg[local socket latency comparison,role
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `concurrent/1` | corosio (kqueue) | 2.06 µs | 0.14% | +95.8%
-| `concurrent/1` | asio (coroutines) | 48.60 µs | 0.08% | +0.0%
-| `concurrent/1` | asio (callbacks) | 48.62 µs | 0.09% | baseline
-| `concurrent/16` | corosio (kqueue) | 30.67 µs | 0.18% | +58.8%
-| `concurrent/16` | asio (coroutines) | 77.22 µs | 0.51% | -3.6%
-| `concurrent/16` | asio (callbacks) | 74.53 µs | 0.68% | baseline
-| `concurrent/4` | corosio (kqueue) | 7.69 µs | 0.28% | +86.1%
-| `concurrent/4` | asio (coroutines) | 55.63 µs | 0.21% | -0.5%
-| `concurrent/4` | asio (callbacks) | 55.38 µs | 0.19% | baseline
-| `concurrent_lockless/1` | corosio (kqueue) | 2.03 µs | 0.17% | +95.8%
-| `concurrent_lockless/1` | asio (coroutines) | 48.60 µs | 0.13% | +0.0%
-| `concurrent_lockless/1` | asio (callbacks) | 48.61 µs | 0.04% | baseline
-| `concurrent_lockless/16` | corosio (kqueue) | 30.25 µs | 0.31% | +58.6%
-| `concurrent_lockless/16` | asio (coroutines) | 75.99 µs | 0.92% | -4.1%
-| `concurrent_lockless/16` | asio (callbacks) | 73.02 µs | 0.32% | baseline
-| `concurrent_lockless/4` | corosio (kqueue) | 7.54 µs | 0.14% | +86.4%
-| `concurrent_lockless/4` | asio (coroutines) | 55.41 µs | 0.25% | -0.1%
-| `concurrent_lockless/4` | asio (callbacks) | 55.33 µs | 0.49% | baseline
-| `pingpong/1` | corosio (kqueue) | 2.06 µs | 0.19% | +95.8%
-| `pingpong/1` | asio (coroutines) | 48.62 µs | 0.03% | -0.0%
-| `pingpong/1` | asio (callbacks) | 48.61 µs | 0.10% | baseline
-| `pingpong/1024` | corosio (kqueue) | 2.16 µs | 0.24% | +95.6%
-| `pingpong/1024` | asio (coroutines) | 48.64 µs | 0.15% | -0.1%
-| `pingpong/1024` | asio (callbacks) | 48.60 µs | 0.12% | baseline
-| `pingpong/64` | corosio (kqueue) | 2.06 µs | 0.36% | +95.8%
-| `pingpong/64` | asio (coroutines) | 48.58 µs | 0.03% | +0.0%
-| `pingpong/64` | asio (callbacks) | 48.59 µs | 0.14% | baseline
-| `pingpong_lockless/1` | corosio (kqueue) | 2.03 µs | 0.15% | +95.8%
-| `pingpong_lockless/1` | asio (coroutines) | 48.60 µs | 0.06% | -0.0%
-| `pingpong_lockless/1` | asio (callbacks) | 48.58 µs | 0.07% | baseline
-| `pingpong_lockless/1024` | corosio (kqueue) | 2.13 µs | 0.28% | +95.6%
-| `pingpong_lockless/1024` | asio (coroutines) | 48.60 µs | 0.06% | +0.0%
-| `pingpong_lockless/1024` | asio (callbacks) | 48.61 µs | 0.08% | baseline
-| `pingpong_lockless/64` | corosio (kqueue) | 2.03 µs | 0.27% | +95.8%
-| `pingpong_lockless/64` | asio (coroutines) | 48.58 µs | 0.04% | +0.0%
-| `pingpong_lockless/64` | asio (callbacks) | 48.58 µs | 0.04% | baseline
+| `concurrent/1` | corosio (kqueue) | 1.84 µs | 0.53% | +96.2%
+| `concurrent/1` | asio (coroutines) | 48.60 µs | 0.18% | +0.0%
+| `concurrent/1` | asio (callbacks) | 48.62 µs | 0.03% | baseline
+| `concurrent/16` | corosio (kqueue) | 27.39 µs | 0.45% | +63.0%
+| `concurrent/16` | asio (coroutines) | 76.55 µs | 0.73% | -3.4%
+| `concurrent/16` | asio (callbacks) | 74.01 µs | 0.51% | baseline
+| `concurrent/4` | corosio (kqueue) | 6.87 µs | 0.33% | +87.6%
+| `concurrent/4` | asio (coroutines) | 55.47 µs | 0.25% | +0.1%
+| `concurrent/4` | asio (callbacks) | 55.51 µs | 0.28% | baseline
+| `concurrent_lockless/1` | corosio (kqueue) | 1.82 µs | 0.30% | +96.2%
+| `concurrent_lockless/1` | asio (coroutines) | 48.61 µs | 0.13% | +0.0%
+| `concurrent_lockless/1` | asio (callbacks) | 48.62 µs | 0.05% | baseline
+| `concurrent_lockless/16` | corosio (kqueue) | 27.24 µs | 0.37% | +62.7%
+| `concurrent_lockless/16` | asio (coroutines) | 77.21 µs | 1.71% | -5.8%
+| `concurrent_lockless/16` | asio (callbacks) | 72.98 µs | 0.37% | baseline
+| `concurrent_lockless/4` | corosio (kqueue) | 6.83 µs | 0.38% | +87.7%
+| `concurrent_lockless/4` | asio (coroutines) | 55.54 µs | 0.29% | -0.3%
+| `concurrent_lockless/4` | asio (callbacks) | 55.36 µs | 0.12% | baseline
+| `pingpong/1` | corosio (kqueue) | 1.83 µs | 0.36% | +96.2%
+| `pingpong/1` | asio (coroutines) | 48.62 µs | 0.07% | +0.0%
+| `pingpong/1` | asio (callbacks) | 48.63 µs | 0.03% | baseline
+| `pingpong/1024` | corosio (kqueue) | 1.93 µs | 0.45% | +96.0%
+| `pingpong/1024` | asio (coroutines) | 48.63 µs | 0.04% | -0.0%
+| `pingpong/1024` | asio (callbacks) | 48.63 µs | 0.12% | baseline
+| `pingpong/64` | corosio (kqueue) | 1.84 µs | 0.25% | +96.2%
+| `pingpong/64` | asio (coroutines) | 48.62 µs | 0.03% | -0.0%
+| `pingpong/64` | asio (callbacks) | 48.62 µs | 0.03% | baseline
+| `pingpong_lockless/1` | corosio (kqueue) | 1.82 µs | 3.18% | +96.3%
+| `pingpong_lockless/1` | asio (coroutines) | 48.60 µs | 0.02% | +0.0%
+| `pingpong_lockless/1` | asio (callbacks) | 48.62 µs | 0.04% | baseline
+| `pingpong_lockless/1024` | corosio (kqueue) | 1.92 µs | 0.45% | +96.1%
+| `pingpong_lockless/1024` | asio (coroutines) | 48.63 µs | 0.08% | +0.0%
+| `pingpong_lockless/1024` | asio (callbacks) | 48.64 µs | 0.23% | baseline
+| `pingpong_lockless/64` | corosio (kqueue) | 1.82 µs | 0.36% | +96.3%
+| `pingpong_lockless/64` | asio (coroutines) | 48.62 µs | 0.04% | -0.0%
+| `pingpong_lockless/64` | asio (callbacks) | 48.60 µs | 0.09% | baseline
|===
====
@@ -308,42 +308,42 @@ image::bench/macos-local_socket_throughput-g1.svg[local socket throughput compar
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `bidirectional/1024` | corosio (kqueue) | 1.22 GB/s | 0.26% | +703.2%
-| `bidirectional/1024` | asio (coroutines) | 151.7 MB/s | 0.18% | -0.1%
-| `bidirectional/1024` | asio (callbacks) | 151.9 MB/s | 0.04% | baseline
-| `bidirectional/1048576` | corosio (kqueue) | 3.85 GB/s | 0.45% | +246.9%
-| `bidirectional/1048576` | asio (coroutines) | 1.11 GB/s | 0.05% | -0.3%
-| `bidirectional/1048576` | asio (callbacks) | 1.11 GB/s | 0.07% | baseline
-| `bidirectional/16384` | corosio (kqueue) | 3.85 GB/s | 0.63% | +246.6%
-| `bidirectional/16384` | asio (coroutines) | 1.11 GB/s | 0.05% | -0.2%
-| `bidirectional/16384` | asio (callbacks) | 1.11 GB/s | 0.38% | baseline
-| `bidirectional/262144` | corosio (kqueue) | 3.86 GB/s | 0.72% | +247.3%
-| `bidirectional/262144` | asio (coroutines) | 1.11 GB/s | 0.02% | -0.3%
-| `bidirectional/262144` | asio (callbacks) | 1.11 GB/s | 0.23% | baseline
-| `bidirectional/4096` | corosio (kqueue) | 2.90 GB/s | 0.37% | +377.7%
-| `bidirectional/4096` | asio (coroutines) | 605.1 MB/s | 0.30% | -0.3%
-| `bidirectional/4096` | asio (callbacks) | 606.7 MB/s | 0.13% | baseline
-| `bidirectional/65536` | corosio (kqueue) | 3.85 GB/s | 0.32% | +247.0%
-| `bidirectional/65536` | asio (coroutines) | 1.11 GB/s | 0.03% | -0.3%
-| `bidirectional/65536` | asio (callbacks) | 1.11 GB/s | 0.31% | baseline
-| `bidirectional_lockless/1024` | corosio (kqueue) | 1.23 GB/s | 0.14% | +708.6%
-| `bidirectional_lockless/1024` | asio (coroutines) | 151.8 MB/s | 0.05% | -0.1%
-| `bidirectional_lockless/1024` | asio (callbacks) | 151.9 MB/s | 0.04% | baseline
-| `bidirectional_lockless/1048576` | corosio (kqueue) | 3.92 GB/s | 0.32% | +242.0%
-| `bidirectional_lockless/1048576` | asio (coroutines) | 1.11 GB/s | 0.03% | -3.3%
-| `bidirectional_lockless/1048576` | asio (callbacks) | 1.14 GB/s | 1.59% | baseline
-| `bidirectional_lockless/16384` | corosio (kqueue) | 3.90 GB/s | 0.54% | +240.9%
-| `bidirectional_lockless/16384` | asio (coroutines) | 1.11 GB/s | 0.03% | -3.1%
-| `bidirectional_lockless/16384` | asio (callbacks) | 1.14 GB/s | 1.35% | baseline
-| `bidirectional_lockless/262144` | corosio (kqueue) | 3.90 GB/s | 0.43% | +241.4%
-| `bidirectional_lockless/262144` | asio (coroutines) | 1.11 GB/s | 0.02% | -3.1%
-| `bidirectional_lockless/262144` | asio (callbacks) | 1.14 GB/s | 1.55% | baseline
-| `bidirectional_lockless/4096` | corosio (kqueue) | 2.95 GB/s | 0.38% | +384.9%
-| `bidirectional_lockless/4096` | asio (coroutines) | 605.8 MB/s | 0.16% | -0.3%
-| `bidirectional_lockless/4096` | asio (callbacks) | 607.4 MB/s | 0.05% | baseline
-| `bidirectional_lockless/65536` | corosio (kqueue) | 3.89 GB/s | 0.47% | +242.3%
-| `bidirectional_lockless/65536` | asio (coroutines) | 1.11 GB/s | 0.02% | -2.6%
-| `bidirectional_lockless/65536` | asio (callbacks) | 1.14 GB/s | 1.77% | baseline
+| `bidirectional/1024` | corosio (kqueue) | 1.30 GB/s | 1.90% | +755.3%
+| `bidirectional/1024` | asio (coroutines) | 151.7 MB/s | 0.03% | -0.1%
+| `bidirectional/1024` | asio (callbacks) | 151.9 MB/s | 0.14% | baseline
+| `bidirectional/1048576` | corosio (kqueue) | 3.90 GB/s | 0.57% | +249.9%
+| `bidirectional/1048576` | asio (coroutines) | 1.11 GB/s | 0.03% | -0.8%
+| `bidirectional/1048576` | asio (callbacks) | 1.12 GB/s | 0.27% | baseline
+| `bidirectional/16384` | corosio (kqueue) | 3.91 GB/s | 0.51% | +250.8%
+| `bidirectional/16384` | asio (coroutines) | 1.11 GB/s | 0.04% | -0.6%
+| `bidirectional/16384` | asio (callbacks) | 1.11 GB/s | 0.69% | baseline
+| `bidirectional/262144` | corosio (kqueue) | 3.91 GB/s | 0.64% | +250.3%
+| `bidirectional/262144` | asio (coroutines) | 1.11 GB/s | 0.06% | -0.7%
+| `bidirectional/262144` | asio (callbacks) | 1.12 GB/s | 0.71% | baseline
+| `bidirectional/4096` | corosio (kqueue) | 2.93 GB/s | 0.84% | +383.4%
+| `bidirectional/4096` | asio (coroutines) | 605.5 MB/s | 0.05% | -0.2%
+| `bidirectional/4096` | asio (callbacks) | 606.7 MB/s | 0.14% | baseline
+| `bidirectional/65536` | corosio (kqueue) | 3.91 GB/s | 0.36% | +250.3%
+| `bidirectional/65536` | asio (coroutines) | 1.11 GB/s | 0.02% | -0.8%
+| `bidirectional/65536` | asio (callbacks) | 1.12 GB/s | 0.52% | baseline
+| `bidirectional_lockless/1024` | corosio (kqueue) | 1.30 GB/s | 0.37% | +757.0%
+| `bidirectional_lockless/1024` | asio (coroutines) | 151.8 MB/s | 0.08% | -0.1%
+| `bidirectional_lockless/1024` | asio (callbacks) | 151.9 MB/s | 0.03% | baseline
+| `bidirectional_lockless/1048576` | corosio (kqueue) | 3.97 GB/s | 0.29% | +247.0%
+| `bidirectional_lockless/1048576` | asio (coroutines) | 1.11 GB/s | 0.10% | -3.2%
+| `bidirectional_lockless/1048576` | asio (callbacks) | 1.14 GB/s | 1.70% | baseline
+| `bidirectional_lockless/16384` | corosio (kqueue) | 4.00 GB/s | 0.58% | +248.3%
+| `bidirectional_lockless/16384` | asio (coroutines) | 1.11 GB/s | 0.26% | -3.4%
+| `bidirectional_lockless/16384` | asio (callbacks) | 1.15 GB/s | 1.42% | baseline
+| `bidirectional_lockless/262144` | corosio (kqueue) | 3.99 GB/s | 0.54% | +245.3%
+| `bidirectional_lockless/262144` | asio (coroutines) | 1.11 GB/s | 0.09% | -4.1%
+| `bidirectional_lockless/262144` | asio (callbacks) | 1.16 GB/s | 2.21% | baseline
+| `bidirectional_lockless/4096` | corosio (kqueue) | 2.97 GB/s | 0.71% | +388.9%
+| `bidirectional_lockless/4096` | asio (coroutines) | 606.0 MB/s | 0.12% | -0.2%
+| `bidirectional_lockless/4096` | asio (callbacks) | 606.9 MB/s | 0.11% | baseline
+| `bidirectional_lockless/65536` | corosio (kqueue) | 3.99 GB/s | 0.52% | +246.0%
+| `bidirectional_lockless/65536` | asio (coroutines) | 1.11 GB/s | 0.07% | -4.0%
+| `bidirectional_lockless/65536` | asio (callbacks) | 1.15 GB/s | 2.14% | baseline
|===
====
@@ -359,42 +359,42 @@ image::bench/macos-local_socket_throughput-g2.svg[local socket throughput compar
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `unidirectional/1024` | corosio (kqueue) | 1.19 GB/s | 0.36% | +1402.1%
-| `unidirectional/1024` | asio (coroutines) | 76.19 MB/s | 0.04% | -4.0%
-| `unidirectional/1024` | asio (callbacks) | 79.38 MB/s | 0.75% | baseline
-| `unidirectional/1048576` | corosio (kqueue) | 3.46 GB/s | 0.31% | +467.8%
-| `unidirectional/1048576` | asio (coroutines) | 608.5 MB/s | 0.08% | -0.1%
-| `unidirectional/1048576` | asio (callbacks) | 608.9 MB/s | 0.18% | baseline
-| `unidirectional/16384` | corosio (kqueue) | 3.46 GB/s | 0.38% | +467.9%
-| `unidirectional/16384` | asio (coroutines) | 608.6 MB/s | 0.03% | -0.0%
-| `unidirectional/16384` | asio (callbacks) | 608.7 MB/s | 0.03% | baseline
-| `unidirectional/262144` | corosio (kqueue) | 3.45 GB/s | 0.25% | +466.7%
-| `unidirectional/262144` | asio (coroutines) | 608.6 MB/s | 0.03% | -0.0%
-| `unidirectional/262144` | asio (callbacks) | 608.8 MB/s | 0.03% | baseline
-| `unidirectional/4096` | corosio (kqueue) | 2.68 GB/s | 0.21% | +778.7%
-| `unidirectional/4096` | asio (coroutines) | 304.5 MB/s | 0.08% | -0.1%
-| `unidirectional/4096` | asio (callbacks) | 304.8 MB/s | 0.02% | baseline
-| `unidirectional/65536` | corosio (kqueue) | 3.44 GB/s | 0.42% | +465.7%
-| `unidirectional/65536` | asio (coroutines) | 608.7 MB/s | 0.02% | -0.0%
-| `unidirectional/65536` | asio (callbacks) | 608.8 MB/s | 0.09% | baseline
-| `unidirectional_lockless/1024` | corosio (kqueue) | 1.20 GB/s | 0.26% | +1335.5%
-| `unidirectional_lockless/1024` | asio (coroutines) | 77.56 MB/s | 0.32% | -7.0%
-| `unidirectional_lockless/1024` | asio (callbacks) | 83.40 MB/s | 0.26% | baseline
-| `unidirectional_lockless/1048576` | corosio (kqueue) | 3.50 GB/s | 0.43% | +474.9%
-| `unidirectional_lockless/1048576` | asio (coroutines) | 608.6 MB/s | 0.04% | -0.1%
-| `unidirectional_lockless/1048576` | asio (callbacks) | 609.0 MB/s | 0.03% | baseline
-| `unidirectional_lockless/16384` | corosio (kqueue) | 3.50 GB/s | 0.34% | +475.4%
-| `unidirectional_lockless/16384` | asio (coroutines) | 608.7 MB/s | 0.01% | -0.0%
-| `unidirectional_lockless/16384` | asio (callbacks) | 608.9 MB/s | 0.03% | baseline
-| `unidirectional_lockless/262144` | corosio (kqueue) | 3.50 GB/s | 0.34% | +475.1%
-| `unidirectional_lockless/262144` | asio (coroutines) | 608.6 MB/s | 0.05% | -0.1%
-| `unidirectional_lockless/262144` | asio (callbacks) | 608.9 MB/s | 0.02% | baseline
-| `unidirectional_lockless/4096` | corosio (kqueue) | 2.71 GB/s | 0.22% | +776.8%
-| `unidirectional_lockless/4096` | asio (coroutines) | 304.6 MB/s | 0.03% | -1.6%
-| `unidirectional_lockless/4096` | asio (callbacks) | 309.5 MB/s | 0.58% | baseline
-| `unidirectional_lockless/65536` | corosio (kqueue) | 3.50 GB/s | 0.42% | +474.0%
-| `unidirectional_lockless/65536` | asio (coroutines) | 608.7 MB/s | 0.02% | -0.0%
-| `unidirectional_lockless/65536` | asio (callbacks) | 608.9 MB/s | 0.03% | baseline
+| `unidirectional/1024` | corosio (kqueue) | 1.27 GB/s | 0.26% | +1453.7%
+| `unidirectional/1024` | asio (coroutines) | 76.50 MB/s | 0.37% | -6.7%
+| `unidirectional/1024` | asio (callbacks) | 82.02 MB/s | 1.50% | baseline
+| `unidirectional/1048576` | corosio (kqueue) | 3.54 GB/s | 0.40% | +482.0%
+| `unidirectional/1048576` | asio (coroutines) | 608.4 MB/s | 0.02% | -0.0%
+| `unidirectional/1048576` | asio (callbacks) | 608.5 MB/s | 0.07% | baseline
+| `unidirectional/16384` | corosio (kqueue) | 3.54 GB/s | 0.24% | +481.8%
+| `unidirectional/16384` | asio (coroutines) | 608.3 MB/s | 0.13% | -0.1%
+| `unidirectional/16384` | asio (callbacks) | 608.6 MB/s | 0.02% | baseline
+| `unidirectional/262144` | corosio (kqueue) | 3.54 GB/s | 0.31% | +481.5%
+| `unidirectional/262144` | asio (coroutines) | 608.3 MB/s | 0.06% | -0.0%
+| `unidirectional/262144` | asio (callbacks) | 608.5 MB/s | 0.04% | baseline
+| `unidirectional/4096` | corosio (kqueue) | 2.73 GB/s | 0.10% | +793.8%
+| `unidirectional/4096` | asio (coroutines) | 304.5 MB/s | 0.02% | -0.3%
+| `unidirectional/4096` | asio (callbacks) | 305.3 MB/s | 0.30% | baseline
+| `unidirectional/65536` | corosio (kqueue) | 3.54 GB/s | 0.21% | +482.5%
+| `unidirectional/65536` | asio (coroutines) | 608.3 MB/s | 0.02% | -0.0%
+| `unidirectional/65536` | asio (callbacks) | 608.5 MB/s | 0.04% | baseline
+| `unidirectional_lockless/1024` | corosio (kqueue) | 1.28 GB/s | 0.64% | +1434.4%
+| `unidirectional_lockless/1024` | asio (coroutines) | 79.13 MB/s | 0.72% | -5.3%
+| `unidirectional_lockless/1024` | asio (callbacks) | 83.58 MB/s | 0.30% | baseline
+| `unidirectional_lockless/1048576` | corosio (kqueue) | 3.61 GB/s | 0.28% | +492.7%
+| `unidirectional_lockless/1048576` | asio (coroutines) | 608.5 MB/s | 0.02% | -0.0%
+| `unidirectional_lockless/1048576` | asio (callbacks) | 608.7 MB/s | 0.03% | baseline
+| `unidirectional_lockless/16384` | corosio (kqueue) | 3.61 GB/s | 0.42% | +493.1%
+| `unidirectional_lockless/16384` | asio (coroutines) | 608.4 MB/s | 0.04% | -0.0%
+| `unidirectional_lockless/16384` | asio (callbacks) | 608.7 MB/s | 0.01% | baseline
+| `unidirectional_lockless/262144` | corosio (kqueue) | 3.60 GB/s | 0.29% | +490.8%
+| `unidirectional_lockless/262144` | asio (coroutines) | 608.5 MB/s | 0.04% | -0.0%
+| `unidirectional_lockless/262144` | asio (callbacks) | 608.8 MB/s | 0.01% | baseline
+| `unidirectional_lockless/4096` | corosio (kqueue) | 2.77 GB/s | 0.32% | +787.4%
+| `unidirectional_lockless/4096` | asio (coroutines) | 304.7 MB/s | 0.04% | -2.2%
+| `unidirectional_lockless/4096` | asio (callbacks) | 311.6 MB/s | 0.46% | baseline
+| `unidirectional_lockless/65536` | corosio (kqueue) | 3.60 GB/s | 0.15% | +492.0%
+| `unidirectional_lockless/65536` | asio (coroutines) | 608.6 MB/s | 0.06% | -0.0%
+| `unidirectional_lockless/65536` | asio (callbacks) | 608.7 MB/s | 0.03% | baseline
|===
====
@@ -418,42 +418,42 @@ image::bench/macos-socket_latency.svg[socket latency comparison,role=bch-block,o
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `concurrent/1` | corosio (kqueue) | 18.82 µs | 0.21% | +64.8%
-| `concurrent/1` | asio (coroutines) | 55.96 µs | 2.40% | -4.6%
-| `concurrent/1` | asio (callbacks) | 53.52 µs | 4.64% | baseline
-| `concurrent/16` | corosio (kqueue) | 120.69 µs | 0.53% | +9.5%
-| `concurrent/16` | asio (coroutines) | 142.60 µs | 5.34% | -6.9%
-| `concurrent/16` | asio (callbacks) | 133.43 µs | 5.65% | baseline
-| `concurrent/4` | corosio (kqueue) | 44.09 µs | 0.77% | +40.3%
-| `concurrent/4` | asio (coroutines) | 74.88 µs | 7.32% | -1.3%
-| `concurrent/4` | asio (callbacks) | 73.91 µs | 0.80% | baseline
-| `concurrent_lockless/1` | corosio (kqueue) | 18.85 µs | 0.49% | +66.7%
-| `concurrent_lockless/1` | asio (coroutines) | 55.13 µs | 3.89% | +2.6%
-| `concurrent_lockless/1` | asio (callbacks) | 56.61 µs | 6.54% | baseline
-| `concurrent_lockless/16` | corosio (kqueue) | 120.26 µs | 0.39% | +8.3%
-| `concurrent_lockless/16` | asio (coroutines) | 136.84 µs | 5.71% | -4.3%
-| `concurrent_lockless/16` | asio (callbacks) | 131.16 µs | 7.19% | baseline
-| `concurrent_lockless/4` | corosio (kqueue) | 43.39 µs | 0.67% | +40.9%
-| `concurrent_lockless/4` | asio (coroutines) | 74.37 µs | 13.79% | -1.2%
-| `concurrent_lockless/4` | asio (callbacks) | 73.46 µs | 0.93% | baseline
-| `pingpong/1` | corosio (kqueue) | 15.56 µs | 0.60% | +68.5%
-| `pingpong/1` | asio (coroutines) | 50.73 µs | 1.93% | -2.6%
-| `pingpong/1` | asio (callbacks) | 49.42 µs | 2.41% | baseline
-| `pingpong/1024` | corosio (kqueue) | 19.02 µs | 0.25% | +66.2%
-| `pingpong/1024` | asio (coroutines) | 53.34 µs | 6.26% | +5.1%
-| `pingpong/1024` | asio (callbacks) | 56.18 µs | 5.76% | baseline
-| `pingpong/64` | corosio (kqueue) | 18.81 µs | 0.51% | +66.8%
-| `pingpong/64` | asio (coroutines) | 56.64 µs | 3.02% | -0.0%
-| `pingpong/64` | asio (callbacks) | 56.62 µs | 4.45% | baseline
-| `pingpong_lockless/1` | corosio (kqueue) | 15.47 µs | 0.43% | +69.7%
-| `pingpong_lockless/1` | asio (coroutines) | 55.05 µs | 5.28% | -7.8%
-| `pingpong_lockless/1` | asio (callbacks) | 51.09 µs | 5.04% | baseline
-| `pingpong_lockless/1024` | corosio (kqueue) | 19.03 µs | 0.36% | +66.4%
-| `pingpong_lockless/1024` | asio (coroutines) | 56.89 µs | 2.43% | -0.4%
-| `pingpong_lockless/1024` | asio (callbacks) | 56.67 µs | 2.05% | baseline
-| `pingpong_lockless/64` | corosio (kqueue) | 18.85 µs | 0.41% | +66.8%
-| `pingpong_lockless/64` | asio (coroutines) | 56.61 µs | 3.37% | +0.4%
-| `pingpong_lockless/64` | asio (callbacks) | 56.84 µs | 4.40% | baseline
+| `concurrent/1` | corosio (kqueue) | 18.70 µs | 0.14% | +65.0%
+| `concurrent/1` | asio (coroutines) | 54.59 µs | 4.46% | -2.2%
+| `concurrent/1` | asio (callbacks) | 53.43 µs | 7.78% | baseline
+| `concurrent/16` | corosio (kqueue) | 120.50 µs | 0.83% | +2.7%
+| `concurrent/16` | asio (coroutines) | 127.88 µs | 5.58% | -3.3%
+| `concurrent/16` | asio (callbacks) | 123.83 µs | 7.30% | baseline
+| `concurrent/4` | corosio (kqueue) | 43.02 µs | 1.24% | +36.7%
+| `concurrent/4` | asio (coroutines) | 74.36 µs | 10.62% | -9.5%
+| `concurrent/4` | asio (callbacks) | 67.91 µs | 12.82% | baseline
+| `concurrent_lockless/1` | corosio (kqueue) | 18.71 µs | 0.44% | +61.1%
+| `concurrent_lockless/1` | asio (coroutines) | 50.25 µs | 6.17% | -4.6%
+| `concurrent_lockless/1` | asio (callbacks) | 48.04 µs | 11.74% | baseline
+| `concurrent_lockless/16` | corosio (kqueue) | 119.65 µs | 0.91% | +7.2%
+| `concurrent_lockless/16` | asio (coroutines) | 125.29 µs | 6.16% | +2.8%
+| `concurrent_lockless/16` | asio (callbacks) | 128.92 µs | 5.65% | baseline
+| `concurrent_lockless/4` | corosio (kqueue) | 42.35 µs | 0.95% | +41.8%
+| `concurrent_lockless/4` | asio (coroutines) | 73.02 µs | 13.57% | -0.3%
+| `concurrent_lockless/4` | asio (callbacks) | 72.79 µs | 0.27% | baseline
+| `pingpong/1` | corosio (kqueue) | 15.39 µs | 0.92% | +67.2%
+| `pingpong/1` | asio (coroutines) | 48.16 µs | 4.59% | -2.5%
+| `pingpong/1` | asio (callbacks) | 46.97 µs | 3.56% | baseline
+| `pingpong/1024` | corosio (kqueue) | 19.03 µs | 0.13% | +66.4%
+| `pingpong/1024` | asio (coroutines) | 57.03 µs | 8.98% | -0.6%
+| `pingpong/1024` | asio (callbacks) | 56.69 µs | 4.87% | baseline
+| `pingpong/64` | corosio (kqueue) | 18.70 µs | 0.85% | +67.2%
+| `pingpong/64` | asio (coroutines) | 56.77 µs | 3.18% | +0.3%
+| `pingpong/64` | asio (callbacks) | 56.93 µs | 3.98% | baseline
+| `pingpong_lockless/1` | corosio (kqueue) | 15.35 µs | 0.07% | +71.2%
+| `pingpong_lockless/1` | asio (coroutines) | 53.87 µs | 8.90% | -1.0%
+| `pingpong_lockless/1` | asio (callbacks) | 53.32 µs | 3.14% | baseline
+| `pingpong_lockless/1024` | corosio (kqueue) | 19.05 µs | 0.14% | +66.4%
+| `pingpong_lockless/1024` | asio (coroutines) | 55.78 µs | 2.69% | +1.7%
+| `pingpong_lockless/1024` | asio (callbacks) | 56.75 µs | 8.28% | baseline
+| `pingpong_lockless/64` | corosio (kqueue) | 18.68 µs | 0.07% | +65.1%
+| `pingpong_lockless/64` | asio (coroutines) | 51.41 µs | 8.35% | +4.0%
+| `pingpong_lockless/64` | asio (callbacks) | 53.55 µs | 5.13% | baseline
|===
====
@@ -477,42 +477,42 @@ image::bench/macos-socket_throughput-g1.svg[socket throughput comparison, part 1
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `bidirectional/1024` | corosio (kqueue) | 410.3 MB/s | 0.65% | +100.0%
-| `bidirectional/1024` | asio (coroutines) | 198.8 MB/s | 0.87% | -3.1%
-| `bidirectional/1024` | asio (callbacks) | 205.1 MB/s | 0.67% | baseline
-| `bidirectional/1048576` | corosio (kqueue) | 7.75 GB/s | 0.71% | -11.6%
-| `bidirectional/1048576` | asio (coroutines) | 8.57 GB/s | 1.62% | -2.2%
-| `bidirectional/1048576` | asio (callbacks) | 8.77 GB/s | 2.18% | baseline
-| `bidirectional/16384` | corosio (kqueue) | 4.01 GB/s | 0.58% | +64.9%
-| `bidirectional/16384` | asio (coroutines) | 2.39 GB/s | 0.37% | -1.8%
-| `bidirectional/16384` | asio (callbacks) | 2.43 GB/s | 0.31% | baseline
-| `bidirectional/262144` | corosio (kqueue) | 9.02 GB/s | 1.59% | -1.9%
-| `bidirectional/262144` | asio (coroutines) | 7.37 GB/s | 8.49% | -19.9%
-| `bidirectional/262144` | asio (callbacks) | 9.20 GB/s | 0.56% | baseline
-| `bidirectional/4096` | corosio (kqueue) | 1.49 GB/s | 0.30% | +88.6%
-| `bidirectional/4096` | asio (coroutines) | 756.1 MB/s | 0.87% | -4.2%
-| `bidirectional/4096` | asio (callbacks) | 789.4 MB/s | 0.68% | baseline
-| `bidirectional/65536` | corosio (kqueue) | 7.59 GB/s | 1.46% | +32.1%
-| `bidirectional/65536` | asio (coroutines) | 5.74 GB/s | 1.55% | -0.2%
-| `bidirectional/65536` | asio (callbacks) | 5.75 GB/s | 0.86% | baseline
-| `bidirectional_lockless/1024` | corosio (kqueue) | 411.7 MB/s | 0.57% | +104.4%
-| `bidirectional_lockless/1024` | asio (coroutines) | 201.3 MB/s | 0.67% | -0.1%
-| `bidirectional_lockless/1024` | asio (callbacks) | 201.4 MB/s | 1.34% | baseline
-| `bidirectional_lockless/1048576` | corosio (kqueue) | 7.76 GB/s | 2.00% | -11.3%
-| `bidirectional_lockless/1048576` | asio (coroutines) | 8.72 GB/s | 2.31% | -0.3%
-| `bidirectional_lockless/1048576` | asio (callbacks) | 8.75 GB/s | 2.38% | baseline
-| `bidirectional_lockless/16384` | corosio (kqueue) | 4.00 GB/s | 0.47% | +63.3%
-| `bidirectional_lockless/16384` | asio (coroutines) | 2.40 GB/s | 0.51% | -1.9%
-| `bidirectional_lockless/16384` | asio (callbacks) | 2.45 GB/s | 0.22% | baseline
-| `bidirectional_lockless/262144` | corosio (kqueue) | 8.95 GB/s | 1.93% | -3.8%
-| `bidirectional_lockless/262144` | asio (coroutines) | 7.43 GB/s | 10.71% | -20.2%
-| `bidirectional_lockless/262144` | asio (callbacks) | 9.31 GB/s | 7.51% | baseline
-| `bidirectional_lockless/4096` | corosio (kqueue) | 1.50 GB/s | 0.51% | +86.4%
-| `bidirectional_lockless/4096` | asio (coroutines) | 773.4 MB/s | 0.50% | -3.6%
-| `bidirectional_lockless/4096` | asio (callbacks) | 802.7 MB/s | 1.08% | baseline
-| `bidirectional_lockless/65536` | corosio (kqueue) | 7.82 GB/s | 1.25% | +36.1%
-| `bidirectional_lockless/65536` | asio (coroutines) | 5.74 GB/s | 1.34% | -0.0%
-| `bidirectional_lockless/65536` | asio (callbacks) | 5.75 GB/s | 1.66% | baseline
+| `bidirectional/1024` | corosio (kqueue) | 478.7 MB/s | 0.71% | +133.8%
+| `bidirectional/1024` | asio (coroutines) | 201.7 MB/s | 0.30% | -1.5%
+| `bidirectional/1024` | asio (callbacks) | 204.7 MB/s | 1.10% | baseline
+| `bidirectional/1048576` | corosio (kqueue) | 7.78 GB/s | 1.79% | -10.6%
+| `bidirectional/1048576` | asio (coroutines) | 8.94 GB/s | 3.62% | +2.7%
+| `bidirectional/1048576` | asio (callbacks) | 8.70 GB/s | 3.36% | baseline
+| `bidirectional/16384` | corosio (kqueue) | 4.61 GB/s | 0.65% | +88.8%
+| `bidirectional/16384` | asio (coroutines) | 2.40 GB/s | 0.66% | -1.7%
+| `bidirectional/16384` | asio (callbacks) | 2.44 GB/s | 0.19% | baseline
+| `bidirectional/262144` | corosio (kqueue) | 8.88 GB/s | 1.21% | -2.7%
+| `bidirectional/262144` | asio (coroutines) | 7.39 GB/s | 0.34% | -19.1%
+| `bidirectional/262144` | asio (callbacks) | 9.13 GB/s | 0.98% | baseline
+| `bidirectional/4096` | corosio (kqueue) | 1.83 GB/s | 0.65% | +128.8%
+| `bidirectional/4096` | asio (coroutines) | 777.7 MB/s | 0.65% | -3.0%
+| `bidirectional/4096` | asio (callbacks) | 801.8 MB/s | 0.37% | baseline
+| `bidirectional/65536` | corosio (kqueue) | 7.57 GB/s | 1.16% | +32.5%
+| `bidirectional/65536` | asio (coroutines) | 5.77 GB/s | 0.93% | +0.9%
+| `bidirectional/65536` | asio (callbacks) | 5.72 GB/s | 0.66% | baseline
+| `bidirectional_lockless/1024` | corosio (kqueue) | 480.7 MB/s | 0.89% | +136.3%
+| `bidirectional_lockless/1024` | asio (coroutines) | 205.2 MB/s | 0.42% | +0.9%
+| `bidirectional_lockless/1024` | asio (callbacks) | 203.5 MB/s | 0.61% | baseline
+| `bidirectional_lockless/1048576` | corosio (kqueue) | 7.75 GB/s | 4.50% | -12.3%
+| `bidirectional_lockless/1048576` | asio (coroutines) | 8.44 GB/s | 2.46% | -4.5%
+| `bidirectional_lockless/1048576` | asio (callbacks) | 8.83 GB/s | 3.51% | baseline
+| `bidirectional_lockless/16384` | corosio (kqueue) | 4.68 GB/s | 1.62% | +90.5%
+| `bidirectional_lockless/16384` | asio (coroutines) | 2.42 GB/s | 0.33% | -1.5%
+| `bidirectional_lockless/16384` | asio (callbacks) | 2.45 GB/s | 0.19% | baseline
+| `bidirectional_lockless/262144` | corosio (kqueue) | 8.87 GB/s | 1.68% | -3.6%
+| `bidirectional_lockless/262144` | asio (coroutines) | 7.42 GB/s | 0.47% | -19.3%
+| `bidirectional_lockless/262144` | asio (callbacks) | 9.20 GB/s | 4.18% | baseline
+| `bidirectional_lockless/4096` | corosio (kqueue) | 1.83 GB/s | 0.72% | +125.4%
+| `bidirectional_lockless/4096` | asio (coroutines) | 788.9 MB/s | 0.73% | -3.0%
+| `bidirectional_lockless/4096` | asio (callbacks) | 813.3 MB/s | 0.39% | baseline
+| `bidirectional_lockless/65536` | corosio (kqueue) | 7.65 GB/s | 1.92% | +33.8%
+| `bidirectional_lockless/65536` | asio (coroutines) | 5.73 GB/s | 1.39% | +0.2%
+| `bidirectional_lockless/65536` | asio (callbacks) | 5.71 GB/s | 2.71% | baseline
|===
====
@@ -528,15 +528,15 @@ image::bench/macos-socket_throughput-g2.svg[socket throughput comparison, part 2
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `multithread/2` | corosio (kqueue) | 7.75 GB/s | 1.43% | +2.4%
-| `multithread/2` | asio (coroutines) | 7.76 GB/s | 1.90% | +2.4%
-| `multithread/2` | asio (callbacks) | 7.57 GB/s | 2.22% | baseline
-| `multithread/4` | corosio (kqueue) | 3.92 GB/s | 2.78% | +0.6%
-| `multithread/4` | asio (coroutines) | 4.08 GB/s | 1.87% | +4.8%
-| `multithread/4` | asio (callbacks) | 3.90 GB/s | 22.01% | baseline
-| `multithread/8` | corosio (kqueue) | 3.48 GB/s | 3.73% | -10.8%
-| `multithread/8` | asio (coroutines) | 3.91 GB/s | 3.00% | +0.2%
-| `multithread/8` | asio (callbacks) | 3.90 GB/s | 2.02% | baseline
+| `multithread/2` | corosio (kqueue) | 7.85 GB/s | 3.58% | +2.9%
+| `multithread/2` | asio (coroutines) | 7.54 GB/s | 1.92% | -1.2%
+| `multithread/2` | asio (callbacks) | 7.63 GB/s | 1.60% | baseline
+| `multithread/4` | corosio (kqueue) | 3.93 GB/s | 18.12% | +1.3%
+| `multithread/4` | asio (coroutines) | 3.90 GB/s | 3.59% | +0.5%
+| `multithread/4` | asio (callbacks) | 3.88 GB/s | 2.54% | baseline
+| `multithread/8` | corosio (kqueue) | 3.39 GB/s | 7.31% | -12.5%
+| `multithread/8` | asio (coroutines) | 3.92 GB/s | 2.29% | +1.2%
+| `multithread/8` | asio (callbacks) | 3.87 GB/s | 1.33% | baseline
|===
====
@@ -552,42 +552,42 @@ image::bench/macos-socket_throughput-g3.svg[socket throughput comparison, part 3
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `unidirectional/1024` | corosio (kqueue) | 321.5 MB/s | 1.01% | +94.3%
-| `unidirectional/1024` | asio (coroutines) | 157.8 MB/s | 0.52% | -4.7%
-| `unidirectional/1024` | asio (callbacks) | 165.5 MB/s | 2.47% | baseline
-| `unidirectional/1048576` | corosio (kqueue) | 9.05 GB/s | 1.04% | -0.1%
-| `unidirectional/1048576` | asio (coroutines) | 8.34 GB/s | 5.41% | -8.0%
-| `unidirectional/1048576` | asio (callbacks) | 9.07 GB/s | 1.31% | baseline
-| `unidirectional/16384` | corosio (kqueue) | 3.75 GB/s | 1.25% | +96.0%
-| `unidirectional/16384` | asio (coroutines) | 1.90 GB/s | 0.43% | -0.8%
-| `unidirectional/16384` | asio (callbacks) | 1.92 GB/s | 1.18% | baseline
-| `unidirectional/262144` | corosio (kqueue) | 8.96 GB/s | 2.20% | +14.0%
-| `unidirectional/262144` | asio (coroutines) | 6.07 GB/s | 8.74% | -22.7%
-| `unidirectional/262144` | asio (callbacks) | 7.86 GB/s | 2.31% | baseline
-| `unidirectional/4096` | corosio (kqueue) | 1.24 GB/s | 1.29% | +97.7%
-| `unidirectional/4096` | asio (coroutines) | 602.1 MB/s | 0.54% | -4.4%
-| `unidirectional/4096` | asio (callbacks) | 629.7 MB/s | 1.12% | baseline
-| `unidirectional/65536` | corosio (kqueue) | 7.32 GB/s | 1.44% | +67.2%
-| `unidirectional/65536` | asio (coroutines) | 4.26 GB/s | 1.87% | -2.6%
-| `unidirectional/65536` | asio (callbacks) | 4.37 GB/s | 2.43% | baseline
-| `unidirectional_lockless/1024` | corosio (kqueue) | 328.2 MB/s | 0.51% | +125.2%
-| `unidirectional_lockless/1024` | asio (coroutines) | 159.8 MB/s | 0.58% | +9.6%
-| `unidirectional_lockless/1024` | asio (callbacks) | 145.7 MB/s | 0.59% | baseline
-| `unidirectional_lockless/1048576` | corosio (kqueue) | 9.12 GB/s | 0.81% | +1.2%
-| `unidirectional_lockless/1048576` | asio (coroutines) | 8.25 GB/s | 5.89% | -8.5%
-| `unidirectional_lockless/1048576` | asio (callbacks) | 9.02 GB/s | 1.13% | baseline
-| `unidirectional_lockless/16384` | corosio (kqueue) | 3.76 GB/s | 0.54% | +94.8%
-| `unidirectional_lockless/16384` | asio (coroutines) | 1.90 GB/s | 0.94% | -1.8%
-| `unidirectional_lockless/16384` | asio (callbacks) | 1.93 GB/s | 1.53% | baseline
-| `unidirectional_lockless/262144` | corosio (kqueue) | 9.14 GB/s | 1.74% | +20.4%
-| `unidirectional_lockless/262144` | asio (coroutines) | 6.07 GB/s | 8.88% | -20.0%
-| `unidirectional_lockless/262144` | asio (callbacks) | 7.59 GB/s | 10.28% | baseline
-| `unidirectional_lockless/4096` | corosio (kqueue) | 1.26 GB/s | 0.74% | +96.5%
-| `unidirectional_lockless/4096` | asio (coroutines) | 613.2 MB/s | 0.64% | -4.1%
-| `unidirectional_lockless/4096` | asio (callbacks) | 639.1 MB/s | 0.40% | baseline
-| `unidirectional_lockless/65536` | corosio (kqueue) | 7.39 GB/s | 0.88% | +74.6%
-| `unidirectional_lockless/65536` | asio (coroutines) | 4.20 GB/s | 1.66% | -0.7%
-| `unidirectional_lockless/65536` | asio (callbacks) | 4.23 GB/s | 2.96% | baseline
+| `unidirectional/1024` | corosio (kqueue) | 467.6 MB/s | 1.07% | +178.3%
+| `unidirectional/1024` | asio (coroutines) | 162.1 MB/s | 0.46% | -3.5%
+| `unidirectional/1024` | asio (callbacks) | 168.0 MB/s | 0.33% | baseline
+| `unidirectional/1048576` | corosio (kqueue) | 9.08 GB/s | 2.78% | -0.1%
+| `unidirectional/1048576` | asio (coroutines) | 8.94 GB/s | 4.99% | -1.7%
+| `unidirectional/1048576` | asio (callbacks) | 9.09 GB/s | 1.66% | baseline
+| `unidirectional/16384` | corosio (kqueue) | 4.53 GB/s | 2.14% | +136.4%
+| `unidirectional/16384` | asio (coroutines) | 1.91 GB/s | 0.58% | -0.6%
+| `unidirectional/16384` | asio (callbacks) | 1.92 GB/s | 1.44% | baseline
+| `unidirectional/262144` | corosio (kqueue) | 8.95 GB/s | 1.21% | +13.2%
+| `unidirectional/262144` | asio (coroutines) | 6.06 GB/s | 0.84% | -23.5%
+| `unidirectional/262144` | asio (callbacks) | 7.91 GB/s | 3.36% | baseline
+| `unidirectional/4096` | corosio (kqueue) | 1.77 GB/s | 1.98% | +177.0%
+| `unidirectional/4096` | asio (coroutines) | 620.6 MB/s | 0.38% | -3.0%
+| `unidirectional/4096` | asio (callbacks) | 639.8 MB/s | 0.32% | baseline
+| `unidirectional/65536` | corosio (kqueue) | 7.36 GB/s | 1.01% | +69.4%
+| `unidirectional/65536` | asio (coroutines) | 4.15 GB/s | 2.89% | -4.5%
+| `unidirectional/65536` | asio (callbacks) | 4.35 GB/s | 3.16% | baseline
+| `unidirectional_lockless/1024` | corosio (kqueue) | 488.0 MB/s | 0.88% | +241.0%
+| `unidirectional_lockless/1024` | asio (coroutines) | 153.7 MB/s | 1.33% | +7.4%
+| `unidirectional_lockless/1024` | asio (callbacks) | 143.1 MB/s | 0.70% | baseline
+| `unidirectional_lockless/1048576` | corosio (kqueue) | 9.11 GB/s | 3.43% | +0.7%
+| `unidirectional_lockless/1048576` | asio (coroutines) | 8.48 GB/s | 5.18% | -6.2%
+| `unidirectional_lockless/1048576` | asio (callbacks) | 9.05 GB/s | 1.37% | baseline
+| `unidirectional_lockless/16384` | corosio (kqueue) | 4.60 GB/s | 2.04% | +139.5%
+| `unidirectional_lockless/16384` | asio (coroutines) | 1.91 GB/s | 0.87% | -0.6%
+| `unidirectional_lockless/16384` | asio (callbacks) | 1.92 GB/s | 1.02% | baseline
+| `unidirectional_lockless/262144` | corosio (kqueue) | 8.88 GB/s | 1.74% | +12.2%
+| `unidirectional_lockless/262144` | asio (coroutines) | 6.14 GB/s | 12.73% | -22.5%
+| `unidirectional_lockless/262144` | asio (callbacks) | 7.92 GB/s | 13.63% | baseline
+| `unidirectional_lockless/4096` | corosio (kqueue) | 1.82 GB/s | 1.44% | +185.9%
+| `unidirectional_lockless/4096` | asio (coroutines) | 632.8 MB/s | 1.02% | -0.9%
+| `unidirectional_lockless/4096` | asio (callbacks) | 638.3 MB/s | 0.85% | baseline
+| `unidirectional_lockless/65536` | corosio (kqueue) | 7.47 GB/s | 2.16% | +76.8%
+| `unidirectional_lockless/65536` | asio (coroutines) | 4.15 GB/s | 0.94% | -1.7%
+| `unidirectional_lockless/65536` | asio (callbacks) | 4.22 GB/s | 3.63% | baseline
|===
====
diff --git a/doc/modules/ROOT/pages/benchmarks/windows.adoc b/doc/modules/ROOT/pages/benchmarks/windows.adoc
index 2fd055bf0..6e162e738 100644
--- a/doc/modules/ROOT/pages/benchmarks/windows.adoc
+++ b/doc/modules/ROOT/pages/benchmarks/windows.adoc
@@ -2,13 +2,13 @@
:page-mode: explanation
:toc: left
-_Generated 2026-10-02 from corosio `e2de06fda069` — https://github.com/cppalliance/corosio/actions/runs/37015995763[benchmark run]. This page is fully generated; do not edit by hand (see the xref:benchmarks/index.adoc[Benchmarks landing page])._
+_Generated 2026-11-06 from corosio `0b3830d5c30b` — https://github.com/cppalliance/corosio/actions/runs/42119198783[benchmark run]. This page is fully generated; do not edit by hand (see the xref:benchmarks/index.adoc[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 xref:benchmarks/index.adoc[Methodology] for how these figures are computed.
-**0 faster · 18 within noise · 59 slower** of 77 benchmarks — median **-6.1%** vs Boost.Asio (callbacks) on the same reactor.
+**0 faster · 14 within noise · 63 slower** of 77 benchmarks — median **-5.6%** vs Boost.Asio (callbacks) on the same reactor.
image::bench/windows-summary.svg[summary,role=bch-block,opts=inline]
@@ -24,13 +24,13 @@ image::bench/windows-summary.svg[summary,role=bch-block,opts=inline]
| Compiler | c++.exe (x86_64-posix-seh-rev2, Built by MinGW-W64 project) 12.2.0
| CMake | `cmake version 3.26.3`
| liburing | n/a
-| Boost commit | 39fa1e9a3491bd099b570935b3f3422065f91b03
-| Asio commit | a7dc25b4cb6c49a6946d86ea20664f1027203225
+| Boost commit | b6d874b77b75085a1b35c640a76d37ab8cd9bb97
+| Asio commit | e99d9da6d9b76a222e29dcaf3d2df51c788b7527
| Asio reactor | IOCP
-| Capy commit | a372a6b054261f29497ac0d19c2a9533f9eaad40
-| Corosio commit | e2de06fda069607f34bc957cbefcbd9ba12fddca
-| Corosio branch | pr/benchmark-report
-| Date (UTC) | 2026-10-02
+| Capy commit | bdadc6adef8c8eb79da6454373175bb1428be524
+| Corosio commit | 0b3830d5c30b96e4a95c0248953575ba7ffcd4d1
+| Corosio branch | develop
+| Date (UTC) | 2026-11-05
| Iterations | 7
| Duration per benchmark (s) | 2.0
|===
@@ -51,33 +51,33 @@ image::bench/windows-accept_churn.svg[accept churn comparison,role=bch-block,opt
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `burst/10` | corosio (IOCP) | 1.54K ops/s | 0.38% | -7.8%
-| `burst/10` | asio (coroutines) | 1.70K ops/s | 0.57% | +2.2%
-| `burst/10` | asio (callbacks) | 1.67K ops/s | 0.65% | baseline
-| `burst/100` | corosio (IOCP) | 149.4 ops/s | 0.43% | -8.7%
-| `burst/100` | asio (coroutines) | 171.8 ops/s | 0.54% | +4.9%
-| `burst/100` | asio (callbacks) | 163.8 ops/s | 0.68% | baseline
-| `burst_lockless/10` | corosio (IOCP) | 1.54K ops/s | 0.26% | -7.8%
-| `burst_lockless/10` | asio (coroutines) | 1.72K ops/s | 0.23% | +2.5%
+| `burst/10` | corosio (IOCP) | 1.57K ops/s | 0.60% | -5.6%
+| `burst/10` | asio (coroutines) | 1.69K ops/s | 0.42% | +1.6%
+| `burst/10` | asio (callbacks) | 1.66K ops/s | 0.82% | baseline
+| `burst/100` | corosio (IOCP) | 154.9 ops/s | 0.75% | -5.1%
+| `burst/100` | asio (coroutines) | 170.3 ops/s | 0.59% | +4.3%
+| `burst/100` | asio (callbacks) | 163.3 ops/s | 0.56% | baseline
+| `burst_lockless/10` | corosio (IOCP) | 1.57K ops/s | 0.21% | -5.9%
+| `burst_lockless/10` | asio (coroutines) | 1.70K ops/s | 0.25% | +2.0%
| `burst_lockless/10` | asio (callbacks) | 1.67K ops/s | 0.23% | baseline
-| `burst_lockless/100` | corosio (IOCP) | 154.4 ops/s | 0.73% | -7.7%
-| `burst_lockless/100` | asio (coroutines) | 177.1 ops/s | 0.53% | +5.9%
-| `burst_lockless/100` | asio (callbacks) | 167.2 ops/s | 0.48% | baseline
-| `concurrent/1` | corosio (IOCP) | 12.38K ops/s | 0.31% | -9.8%
-| `concurrent/1` | asio (coroutines) | 13.22K ops/s | 0.09% | -3.6%
-| `concurrent/1` | asio (callbacks) | 13.72K ops/s | 0.18% | baseline
-| `concurrent/16` | corosio (IOCP) | 13.30K ops/s | 0.24% | -7.9%
-| `concurrent/16` | asio (coroutines) | 14.00K ops/s | 0.22% | -3.0%
-| `concurrent/16` | asio (callbacks) | 14.44K ops/s | 0.17% | baseline
-| `concurrent/4` | corosio (IOCP) | 13.02K ops/s | 0.26% | -8.5%
-| `concurrent/4` | asio (coroutines) | 13.81K ops/s | 0.19% | -3.0%
-| `concurrent/4` | asio (callbacks) | 14.24K ops/s | 0.33% | baseline
-| `sequential` | corosio (IOCP) | 12.34K ops/s | 1.24% | -9.7%
-| `sequential` | asio (coroutines) | 13.15K ops/s | 0.17% | -3.8%
-| `sequential` | asio (callbacks) | 13.67K ops/s | 0.18% | baseline
-| `sequential_lockless` | corosio (IOCP) | 12.39K ops/s | 1.32% | -9.5%
-| `sequential_lockless` | asio (coroutines) | 13.20K ops/s | 0.16% | -3.7%
-| `sequential_lockless` | asio (callbacks) | 13.70K ops/s | 0.15% | baseline
+| `burst_lockless/100` | corosio (IOCP) | 160.2 ops/s | 0.42% | -4.4%
+| `burst_lockless/100` | asio (coroutines) | 176.1 ops/s | 0.42% | +5.1%
+| `burst_lockless/100` | asio (callbacks) | 167.6 ops/s | 0.82% | baseline
+| `concurrent/1` | corosio (IOCP) | 12.49K ops/s | 0.44% | -8.7%
+| `concurrent/1` | asio (coroutines) | 13.13K ops/s | 0.32% | -4.1%
+| `concurrent/1` | asio (callbacks) | 13.69K ops/s | 0.25% | baseline
+| `concurrent/16` | corosio (IOCP) | 13.47K ops/s | 0.16% | -6.9%
+| `concurrent/16` | asio (coroutines) | 14.01K ops/s | 0.33% | -3.2%
+| `concurrent/16` | asio (callbacks) | 14.47K ops/s | 0.23% | baseline
+| `concurrent/4` | corosio (IOCP) | 13.14K ops/s | 0.14% | -7.6%
+| `concurrent/4` | asio (coroutines) | 13.67K ops/s | 0.31% | -3.8%
+| `concurrent/4` | asio (callbacks) | 14.22K ops/s | 0.24% | baseline
+| `sequential` | corosio (IOCP) | 12.48K ops/s | 0.42% | -8.5%
+| `sequential` | asio (coroutines) | 13.10K ops/s | 0.20% | -3.9%
+| `sequential` | asio (callbacks) | 13.64K ops/s | 0.20% | baseline
+| `sequential_lockless` | corosio (IOCP) | 12.55K ops/s | 0.29% | -8.2%
+| `sequential_lockless` | asio (coroutines) | 13.15K ops/s | 0.15% | -3.8%
+| `sequential_lockless` | asio (callbacks) | 13.67K ops/s | 0.19% | baseline
|===
====
@@ -101,24 +101,24 @@ image::bench/windows-fan_out-g1.svg[fan out comparison, part 1,role=bch-block,op
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `concurrent_parents/1` | corosio (IOCP) | 7.16K ops/s | 0.30% | -7.4%
-| `concurrent_parents/1` | asio (coroutines) | 6.85K ops/s | 0.38% | -11.3%
-| `concurrent_parents/1` | asio (callbacks) | 7.73K ops/s | 0.21% | baseline
-| `concurrent_parents/16` | corosio (IOCP) | 6.43K ops/s | 0.76% | -10.7%
-| `concurrent_parents/16` | asio (coroutines) | 6.37K ops/s | 0.73% | -11.5%
-| `concurrent_parents/16` | asio (callbacks) | 7.20K ops/s | 0.43% | baseline
-| `concurrent_parents/4` | corosio (IOCP) | 6.90K ops/s | 0.36% | -9.1%
-| `concurrent_parents/4` | asio (coroutines) | 6.81K ops/s | 0.34% | -10.2%
-| `concurrent_parents/4` | asio (callbacks) | 7.59K ops/s | 0.29% | baseline
-| `concurrent_parents_lockless/1` | corosio (IOCP) | 7.15K ops/s | 0.22% | -7.5%
-| `concurrent_parents_lockless/1` | asio (coroutines) | 6.95K ops/s | 0.23% | -10.1%
-| `concurrent_parents_lockless/1` | asio (callbacks) | 7.73K ops/s | 0.16% | baseline
-| `concurrent_parents_lockless/16` | corosio (IOCP) | 6.44K ops/s | 0.63% | -11.1%
-| `concurrent_parents_lockless/16` | asio (coroutines) | 6.42K ops/s | 0.34% | -11.3%
-| `concurrent_parents_lockless/16` | asio (callbacks) | 7.24K ops/s | 0.65% | baseline
-| `concurrent_parents_lockless/4` | corosio (IOCP) | 6.92K ops/s | 0.34% | -9.1%
-| `concurrent_parents_lockless/4` | asio (coroutines) | 6.80K ops/s | 0.23% | -10.5%
-| `concurrent_parents_lockless/4` | asio (callbacks) | 7.61K ops/s | 0.16% | baseline
+| `concurrent_parents/1` | corosio (IOCP) | 7.12K ops/s | 0.33% | -8.3%
+| `concurrent_parents/1` | asio (coroutines) | 6.94K ops/s | 0.75% | -10.6%
+| `concurrent_parents/1` | asio (callbacks) | 7.76K ops/s | 0.14% | baseline
+| `concurrent_parents/16` | corosio (IOCP) | 6.42K ops/s | 0.83% | -11.9%
+| `concurrent_parents/16` | asio (coroutines) | 6.44K ops/s | 0.70% | -11.6%
+| `concurrent_parents/16` | asio (callbacks) | 7.28K ops/s | 0.39% | baseline
+| `concurrent_parents/4` | corosio (IOCP) | 6.84K ops/s | 0.70% | -10.4%
+| `concurrent_parents/4` | asio (coroutines) | 6.90K ops/s | 0.45% | -9.6%
+| `concurrent_parents/4` | asio (callbacks) | 7.63K ops/s | 0.29% | baseline
+| `concurrent_parents_lockless/1` | corosio (IOCP) | 7.10K ops/s | 0.37% | -8.3%
+| `concurrent_parents_lockless/1` | asio (coroutines) | 7.02K ops/s | 0.21% | -9.4%
+| `concurrent_parents_lockless/1` | asio (callbacks) | 7.75K ops/s | 0.37% | baseline
+| `concurrent_parents_lockless/16` | corosio (IOCP) | 6.42K ops/s | 1.14% | -11.7%
+| `concurrent_parents_lockless/16` | asio (coroutines) | 6.53K ops/s | 0.82% | -10.2%
+| `concurrent_parents_lockless/16` | asio (callbacks) | 7.27K ops/s | 0.39% | baseline
+| `concurrent_parents_lockless/4` | corosio (IOCP) | 6.89K ops/s | 0.73% | -9.6%
+| `concurrent_parents_lockless/4` | asio (coroutines) | 6.89K ops/s | 0.33% | -9.6%
+| `concurrent_parents_lockless/4` | asio (callbacks) | 7.63K ops/s | 0.30% | baseline
|===
====
@@ -134,42 +134,42 @@ image::bench/windows-fan_out-g2.svg[fan out comparison, part 2,role=bch-block,op
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `fork_join/1` | corosio (IOCP) | 112.4K ops/s | 0.37% | -8.9%
-| `fork_join/1` | asio (coroutines) | 109.9K ops/s | 0.96% | -11.0%
-| `fork_join/1` | asio (callbacks) | 123.5K ops/s | 0.27% | baseline
-| `fork_join/16` | corosio (IOCP) | 7.15K ops/s | 0.14% | -7.6%
-| `fork_join/16` | asio (coroutines) | 6.85K ops/s | 0.87% | -11.5%
-| `fork_join/16` | asio (callbacks) | 7.74K ops/s | 0.18% | baseline
-| `fork_join/4` | corosio (IOCP) | 29.33K ops/s | 0.26% | -4.8%
-| `fork_join/4` | asio (coroutines) | 27.75K ops/s | 0.28% | -9.9%
-| `fork_join/4` | asio (callbacks) | 30.82K ops/s | 0.17% | baseline
-| `fork_join/64` | corosio (IOCP) | 1.73K ops/s | 0.83% | -8.7%
-| `fork_join/64` | asio (coroutines) | 1.70K ops/s | 0.17% | -9.9%
-| `fork_join/64` | asio (callbacks) | 1.89K ops/s | 0.46% | baseline
-| `fork_join_lockless/1` | corosio (IOCP) | 112.9K ops/s | 0.19% | -8.8%
-| `fork_join_lockless/1` | asio (coroutines) | 109.8K ops/s | 0.53% | -11.3%
-| `fork_join_lockless/1` | asio (callbacks) | 123.7K ops/s | 0.39% | baseline
-| `fork_join_lockless/16` | corosio (IOCP) | 7.16K ops/s | 0.14% | -7.4%
-| `fork_join_lockless/16` | asio (coroutines) | 6.86K ops/s | 0.51% | -11.3%
-| `fork_join_lockless/16` | asio (callbacks) | 7.73K ops/s | 0.26% | baseline
-| `fork_join_lockless/4` | corosio (IOCP) | 29.24K ops/s | 0.33% | -5.1%
-| `fork_join_lockless/4` | asio (coroutines) | 27.80K ops/s | 0.19% | -9.8%
-| `fork_join_lockless/4` | asio (callbacks) | 30.81K ops/s | 0.16% | baseline
-| `fork_join_lockless/64` | corosio (IOCP) | 1.73K ops/s | 0.52% | -8.8%
-| `fork_join_lockless/64` | asio (coroutines) | 1.71K ops/s | 0.37% | -9.8%
-| `fork_join_lockless/64` | asio (callbacks) | 1.90K ops/s | 0.42% | baseline
-| `nested/16` | corosio (IOCP) | 1.70K ops/s | 0.56% | -10.5%
-| `nested/16` | asio (coroutines) | 1.66K ops/s | 0.39% | -12.3%
-| `nested/16` | asio (callbacks) | 1.89K ops/s | 0.26% | baseline
-| `nested/4` | corosio (IOCP) | 6.99K ops/s | 0.24% | -8.9%
-| `nested/4` | asio (coroutines) | 6.65K ops/s | 0.53% | -13.3%
-| `nested/4` | asio (callbacks) | 7.67K ops/s | 0.52% | baseline
-| `nested_lockless/16` | corosio (IOCP) | 1.69K ops/s | 0.40% | -10.7%
-| `nested_lockless/16` | asio (coroutines) | 1.66K ops/s | 0.49% | -12.7%
-| `nested_lockless/16` | asio (callbacks) | 1.90K ops/s | 0.34% | baseline
-| `nested_lockless/4` | corosio (IOCP) | 7.00K ops/s | 0.30% | -9.0%
-| `nested_lockless/4` | asio (coroutines) | 6.66K ops/s | 0.42% | -13.4%
-| `nested_lockless/4` | asio (callbacks) | 7.69K ops/s | 0.63% | baseline
+| `fork_join/1` | corosio (IOCP) | 111.8K ops/s | 0.44% | -10.0%
+| `fork_join/1` | asio (coroutines) | 110.9K ops/s | 0.31% | -10.7%
+| `fork_join/1` | asio (callbacks) | 124.1K ops/s | 0.37% | baseline
+| `fork_join/16` | corosio (IOCP) | 7.10K ops/s | 0.20% | -8.4%
+| `fork_join/16` | asio (coroutines) | 6.92K ops/s | 0.33% | -10.8%
+| `fork_join/16` | asio (callbacks) | 7.76K ops/s | 0.21% | baseline
+| `fork_join/4` | corosio (IOCP) | 28.96K ops/s | 0.35% | -6.4%
+| `fork_join/4` | asio (coroutines) | 27.96K ops/s | 0.23% | -9.6%
+| `fork_join/4` | asio (callbacks) | 30.95K ops/s | 0.45% | baseline
+| `fork_join/64` | corosio (IOCP) | 1.71K ops/s | 0.97% | -10.3%
+| `fork_join/64` | asio (coroutines) | 1.72K ops/s | 0.56% | -10.0%
+| `fork_join/64` | asio (callbacks) | 1.91K ops/s | 0.30% | baseline
+| `fork_join_lockless/1` | corosio (IOCP) | 112.2K ops/s | 0.27% | -10.0%
+| `fork_join_lockless/1` | asio (coroutines) | 110.5K ops/s | 0.61% | -11.4%
+| `fork_join_lockless/1` | asio (callbacks) | 124.7K ops/s | 0.46% | baseline
+| `fork_join_lockless/16` | corosio (IOCP) | 7.10K ops/s | 0.13% | -8.4%
+| `fork_join_lockless/16` | asio (coroutines) | 6.96K ops/s | 0.28% | -10.3%
+| `fork_join_lockless/16` | asio (callbacks) | 7.75K ops/s | 0.12% | baseline
+| `fork_join_lockless/4` | corosio (IOCP) | 28.88K ops/s | 0.20% | -6.7%
+| `fork_join_lockless/4` | asio (coroutines) | 28.04K ops/s | 0.28% | -9.4%
+| `fork_join_lockless/4` | asio (callbacks) | 30.95K ops/s | 0.28% | baseline
+| `fork_join_lockless/64` | corosio (IOCP) | 1.72K ops/s | 0.86% | -10.2%
+| `fork_join_lockless/64` | asio (coroutines) | 1.73K ops/s | 0.67% | -9.4%
+| `fork_join_lockless/64` | asio (callbacks) | 1.91K ops/s | 0.29% | baseline
+| `nested/16` | corosio (IOCP) | 1.68K ops/s | 0.58% | -11.6%
+| `nested/16` | asio (coroutines) | 1.68K ops/s | 0.58% | -11.7%
+| `nested/16` | asio (callbacks) | 1.90K ops/s | 0.35% | baseline
+| `nested/4` | corosio (IOCP) | 6.96K ops/s | 0.30% | -9.7%
+| `nested/4` | asio (coroutines) | 6.68K ops/s | 0.81% | -13.4%
+| `nested/4` | asio (callbacks) | 7.71K ops/s | 0.23% | baseline
+| `nested_lockless/16` | corosio (IOCP) | 1.68K ops/s | 0.78% | -11.5%
+| `nested_lockless/16` | asio (coroutines) | 1.68K ops/s | 0.72% | -11.7%
+| `nested_lockless/16` | asio (callbacks) | 1.90K ops/s | 0.22% | baseline
+| `nested_lockless/4` | corosio (IOCP) | 6.94K ops/s | 0.20% | -10.0%
+| `nested_lockless/4` | asio (coroutines) | 6.63K ops/s | 0.56% | -14.1%
+| `nested_lockless/4` | asio (callbacks) | 7.72K ops/s | 0.34% | baseline
|===
====
@@ -193,39 +193,39 @@ image::bench/windows-http_server.svg[http server comparison,role=bch-block,opts=
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `concurrent/1` | corosio (IOCP) | 111.9K ops/s | 0.42% | -0.8%
-| `concurrent/1` | asio (coroutines) | 107.8K ops/s | 0.33% | -4.5%
-| `concurrent/1` | asio (callbacks) | 112.8K ops/s | 0.37% | baseline
-| `concurrent/16` | corosio (IOCP) | 108.6K ops/s | 0.33% | -1.9%
-| `concurrent/16` | asio (coroutines) | 106.2K ops/s | 0.39% | -4.0%
-| `concurrent/16` | asio (callbacks) | 110.7K ops/s | 0.23% | baseline
-| `concurrent/32` | corosio (IOCP) | 108.1K ops/s | 0.20% | -1.7%
-| `concurrent/32` | asio (coroutines) | 105.6K ops/s | 0.15% | -4.0%
-| `concurrent/32` | asio (callbacks) | 109.9K ops/s | 0.24% | baseline
-| `concurrent/4` | corosio (IOCP) | 109.6K ops/s | 0.24% | -1.1%
-| `concurrent/4` | asio (coroutines) | 106.4K ops/s | 0.26% | -4.0%
-| `concurrent/4` | asio (callbacks) | 110.8K ops/s | 0.35% | baseline
-| `multithread/1` | corosio (IOCP) | 108.0K ops/s | 0.17% | -1.6%
-| `multithread/1` | asio (coroutines) | 105.6K ops/s | 0.24% | -3.7%
-| `multithread/1` | asio (callbacks) | 109.7K ops/s | 0.26% | baseline
-| `multithread/16` | corosio (IOCP) | 268.9K ops/s | 0.21% | -6.1%
-| `multithread/16` | asio (coroutines) | 279.3K ops/s | 0.43% | -2.4%
-| `multithread/16` | asio (callbacks) | 286.3K ops/s | 0.52% | baseline
-| `multithread/2` | corosio (IOCP) | 181.9K ops/s | 0.68% | -2.9%
-| `multithread/2` | asio (coroutines) | 180.1K ops/s | 0.51% | -3.9%
-| `multithread/2` | asio (callbacks) | 187.4K ops/s | 0.47% | baseline
-| `multithread/4` | corosio (IOCP) | 225.9K ops/s | 0.37% | -4.5%
-| `multithread/4` | asio (coroutines) | 228.7K ops/s | 0.65% | -3.3%
-| `multithread/4` | asio (callbacks) | 236.6K ops/s | 0.55% | baseline
-| `multithread/8` | corosio (IOCP) | 268.0K ops/s | 0.42% | -5.8%
-| `multithread/8` | asio (coroutines) | 277.0K ops/s | 0.56% | -2.6%
-| `multithread/8` | asio (callbacks) | 284.6K ops/s | 0.68% | baseline
-| `single_conn` | corosio (IOCP) | 111.8K ops/s | 0.37% | -0.7%
-| `single_conn` | asio (coroutines) | 107.8K ops/s | 0.05% | -4.2%
-| `single_conn` | asio (callbacks) | 112.5K ops/s | 0.26% | baseline
-| `single_conn_lockless` | corosio (IOCP) | 112.2K ops/s | 0.32% | -0.5%
-| `single_conn_lockless` | asio (coroutines) | 107.6K ops/s | 0.56% | -4.5%
-| `single_conn_lockless` | asio (callbacks) | 112.7K ops/s | 0.20% | baseline
+| `concurrent/1` | corosio (IOCP) | 110.6K ops/s | 0.34% | -1.7%
+| `concurrent/1` | asio (coroutines) | 108.8K ops/s | 0.44% | -3.4%
+| `concurrent/1` | asio (callbacks) | 112.6K ops/s | 0.60% | baseline
+| `concurrent/16` | corosio (IOCP) | 107.7K ops/s | 0.25% | -3.4%
+| `concurrent/16` | asio (coroutines) | 107.0K ops/s | 0.17% | -3.9%
+| `concurrent/16` | asio (callbacks) | 111.4K ops/s | 0.27% | baseline
+| `concurrent/32` | corosio (IOCP) | 106.9K ops/s | 0.25% | -3.6%
+| `concurrent/32` | asio (coroutines) | 106.6K ops/s | 0.17% | -3.8%
+| `concurrent/32` | asio (callbacks) | 110.9K ops/s | 0.23% | baseline
+| `concurrent/4` | corosio (IOCP) | 108.4K ops/s | 0.32% | -2.5%
+| `concurrent/4` | asio (coroutines) | 107.5K ops/s | 0.26% | -3.3%
+| `concurrent/4` | asio (callbacks) | 111.2K ops/s | 0.41% | baseline
+| `multithread/1` | corosio (IOCP) | 107.1K ops/s | 0.16% | -3.4%
+| `multithread/1` | asio (coroutines) | 106.6K ops/s | 0.08% | -3.9%
+| `multithread/1` | asio (callbacks) | 110.8K ops/s | 0.22% | baseline
+| `multithread/16` | corosio (IOCP) | 265.2K ops/s | 0.40% | -6.8%
+| `multithread/16` | asio (coroutines) | 277.6K ops/s | 0.55% | -2.4%
+| `multithread/16` | asio (callbacks) | 284.4K ops/s | 0.36% | baseline
+| `multithread/2` | corosio (IOCP) | 180.6K ops/s | 0.43% | -4.1%
+| `multithread/2` | asio (coroutines) | 181.0K ops/s | 0.57% | -3.8%
+| `multithread/2` | asio (callbacks) | 188.3K ops/s | 0.63% | baseline
+| `multithread/4` | corosio (IOCP) | 224.2K ops/s | 0.57% | -4.9%
+| `multithread/4` | asio (coroutines) | 229.5K ops/s | 0.43% | -2.7%
+| `multithread/4` | asio (callbacks) | 235.9K ops/s | 0.38% | baseline
+| `multithread/8` | corosio (IOCP) | 264.7K ops/s | 0.38% | -6.5%
+| `multithread/8` | asio (coroutines) | 275.5K ops/s | 0.33% | -2.7%
+| `multithread/8` | asio (callbacks) | 283.2K ops/s | 0.71% | baseline
+| `single_conn` | corosio (IOCP) | 110.6K ops/s | 0.25% | -2.2%
+| `single_conn` | asio (coroutines) | 108.7K ops/s | 0.51% | -3.9%
+| `single_conn` | asio (callbacks) | 113.1K ops/s | 0.32% | baseline
+| `single_conn_lockless` | corosio (IOCP) | 110.7K ops/s | 0.32% | -2.0%
+| `single_conn_lockless` | asio (coroutines) | 108.5K ops/s | 0.49% | -4.1%
+| `single_conn_lockless` | asio (callbacks) | 113.1K ops/s | 0.38% | baseline
|===
====
@@ -249,42 +249,42 @@ image::bench/windows-socket_latency.svg[socket latency comparison,role=bch-block
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `concurrent/1` | corosio (IOCP) | 7.57 µs | 0.40% | -7.2%
-| `concurrent/1` | asio (coroutines) | 7.48 µs | 0.45% | -5.9%
-| `concurrent/1` | asio (callbacks) | 7.06 µs | 0.17% | baseline
-| `concurrent/16` | corosio (IOCP) | 130.96 µs | 6.14% | -11.2%
-| `concurrent/16` | asio (coroutines) | 127.44 µs | 2.57% | -8.2%
-| `concurrent/16` | asio (callbacks) | 117.75 µs | 3.93% | baseline
-| `concurrent/4` | corosio (IOCP) | 30.40 µs | 0.21% | -7.4%
-| `concurrent/4` | asio (coroutines) | 29.95 µs | 0.34% | -5.9%
-| `concurrent/4` | asio (callbacks) | 28.30 µs | 0.28% | baseline
-| `concurrent_lockless/1` | corosio (IOCP) | 7.57 µs | 0.56% | -7.3%
-| `concurrent_lockless/1` | asio (coroutines) | 7.48 µs | 0.22% | -6.0%
-| `concurrent_lockless/1` | asio (callbacks) | 7.06 µs | 0.17% | baseline
-| `concurrent_lockless/16` | corosio (IOCP) | 121.42 µs | 0.27% | -8.0%
-| `concurrent_lockless/16` | asio (coroutines) | 120.27 µs | 0.37% | -7.0%
-| `concurrent_lockless/16` | asio (callbacks) | 112.43 µs | 0.28% | baseline
-| `concurrent_lockless/4` | corosio (IOCP) | 30.43 µs | 0.42% | -7.6%
-| `concurrent_lockless/4` | asio (coroutines) | 29.95 µs | 0.41% | -5.9%
-| `concurrent_lockless/4` | asio (callbacks) | 28.28 µs | 0.37% | baseline
-| `pingpong/1` | corosio (IOCP) | 7.56 µs | 0.44% | -7.0%
-| `pingpong/1` | asio (coroutines) | 7.45 µs | 0.77% | -5.5%
-| `pingpong/1` | asio (callbacks) | 7.06 µs | 0.28% | baseline
-| `pingpong/1024` | corosio (IOCP) | 7.67 µs | 0.48% | -7.2%
-| `pingpong/1024` | asio (coroutines) | 7.56 µs | 0.37% | -5.7%
-| `pingpong/1024` | asio (callbacks) | 7.16 µs | 0.49% | baseline
-| `pingpong/64` | corosio (IOCP) | 7.60 µs | 0.41% | -7.5%
-| `pingpong/64` | asio (coroutines) | 7.46 µs | 0.22% | -5.5%
-| `pingpong/64` | asio (callbacks) | 7.07 µs | 0.22% | baseline
-| `pingpong_lockless/1` | corosio (IOCP) | 7.53 µs | 0.25% | -7.0%
-| `pingpong_lockless/1` | asio (coroutines) | 7.43 µs | 0.27% | -5.6%
-| `pingpong_lockless/1` | asio (callbacks) | 7.04 µs | 0.35% | baseline
-| `pingpong_lockless/1024` | corosio (IOCP) | 7.69 µs | 0.25% | -7.5%
-| `pingpong_lockless/1024` | asio (coroutines) | 7.56 µs | 0.36% | -5.6%
-| `pingpong_lockless/1024` | asio (callbacks) | 7.15 µs | 0.35% | baseline
-| `pingpong_lockless/64` | corosio (IOCP) | 7.56 µs | 0.17% | -7.0%
-| `pingpong_lockless/64` | asio (coroutines) | 7.47 µs | 0.29% | -5.7%
-| `pingpong_lockless/64` | asio (callbacks) | 7.07 µs | 0.18% | baseline
+| `concurrent/1` | corosio (IOCP) | 7.69 µs | 0.15% | -9.6%
+| `concurrent/1` | asio (coroutines) | 7.42 µs | 0.26% | -5.8%
+| `concurrent/1` | asio (callbacks) | 7.02 µs | 0.33% | baseline
+| `concurrent/16` | corosio (IOCP) | 129.55 µs | 5.48% | -13.7%
+| `concurrent/16` | asio (coroutines) | 128.24 µs | 2.53% | -12.5%
+| `concurrent/16` | asio (callbacks) | 113.98 µs | 1.86% | baseline
+| `concurrent/4` | corosio (IOCP) | 30.83 µs | 0.27% | -9.6%
+| `concurrent/4` | asio (coroutines) | 29.75 µs | 0.22% | -5.8%
+| `concurrent/4` | asio (callbacks) | 28.12 µs | 0.27% | baseline
+| `concurrent_lockless/1` | corosio (IOCP) | 7.68 µs | 0.49% | -9.4%
+| `concurrent_lockless/1` | asio (coroutines) | 7.39 µs | 0.44% | -5.4%
+| `concurrent_lockless/1` | asio (callbacks) | 7.01 µs | 0.27% | baseline
+| `concurrent_lockless/16` | corosio (IOCP) | 123.08 µs | 1.00% | -10.7%
+| `concurrent_lockless/16` | asio (coroutines) | 119.16 µs | 0.41% | -7.1%
+| `concurrent_lockless/16` | asio (callbacks) | 111.24 µs | 0.33% | baseline
+| `concurrent_lockless/4` | corosio (IOCP) | 30.87 µs | 0.22% | -10.0%
+| `concurrent_lockless/4` | asio (coroutines) | 29.72 µs | 0.20% | -5.9%
+| `concurrent_lockless/4` | asio (callbacks) | 28.07 µs | 0.33% | baseline
+| `pingpong/1` | corosio (IOCP) | 7.64 µs | 0.36% | -9.2%
+| `pingpong/1` | asio (coroutines) | 7.40 µs | 0.50% | -5.7%
+| `pingpong/1` | asio (callbacks) | 7.00 µs | 0.29% | baseline
+| `pingpong/1024` | corosio (IOCP) | 7.74 µs | 0.30% | -9.1%
+| `pingpong/1024` | asio (coroutines) | 7.51 µs | 0.52% | -5.9%
+| `pingpong/1024` | asio (callbacks) | 7.10 µs | 0.36% | baseline
+| `pingpong/64` | corosio (IOCP) | 7.66 µs | 0.33% | -9.5%
+| `pingpong/64` | asio (coroutines) | 7.40 µs | 0.42% | -5.8%
+| `pingpong/64` | asio (callbacks) | 6.99 µs | 0.35% | baseline
+| `pingpong_lockless/1` | corosio (IOCP) | 7.68 µs | 0.28% | -10.1%
+| `pingpong_lockless/1` | asio (coroutines) | 7.36 µs | 0.31% | -5.6%
+| `pingpong_lockless/1` | asio (callbacks) | 6.97 µs | 0.45% | baseline
+| `pingpong_lockless/1024` | corosio (IOCP) | 7.79 µs | 0.45% | -9.9%
+| `pingpong_lockless/1024` | asio (coroutines) | 7.50 µs | 0.40% | -5.8%
+| `pingpong_lockless/1024` | asio (callbacks) | 7.09 µs | 0.19% | baseline
+| `pingpong_lockless/64` | corosio (IOCP) | 7.69 µs | 0.41% | -10.2%
+| `pingpong_lockless/64` | asio (coroutines) | 7.42 µs | 0.14% | -6.2%
+| `pingpong_lockless/64` | asio (callbacks) | 6.98 µs | 0.43% | baseline
|===
====
@@ -308,42 +308,42 @@ image::bench/windows-socket_throughput-g1.svg[socket throughput comparison, part
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `bidirectional/1024` | corosio (IOCP) | 279.9 MB/s | 0.32% | -3.0%
-| `bidirectional/1024` | asio (coroutines) | 274.1 MB/s | 0.34% | -5.0%
-| `bidirectional/1024` | asio (callbacks) | 288.6 MB/s | 0.51% | baseline
-| `bidirectional/1048576` | corosio (IOCP) | 4.42 GB/s | 7.80% | -9.0%
-| `bidirectional/1048576` | asio (coroutines) | 4.66 GB/s | 6.82% | -4.2%
-| `bidirectional/1048576` | asio (callbacks) | 4.86 GB/s | 9.63% | baseline
-| `bidirectional/16384` | corosio (IOCP) | 3.75 GB/s | 0.61% | -1.9%
-| `bidirectional/16384` | asio (coroutines) | 3.68 GB/s | 0.34% | -3.8%
-| `bidirectional/16384` | asio (callbacks) | 3.82 GB/s | 0.55% | baseline
-| `bidirectional/262144` | corosio (IOCP) | 9.55 GB/s | 0.83% | +0.2%
-| `bidirectional/262144` | asio (coroutines) | 9.47 GB/s | 6.89% | -0.7%
-| `bidirectional/262144` | asio (callbacks) | 9.54 GB/s | 0.42% | baseline
-| `bidirectional/4096` | corosio (IOCP) | 1.07 GB/s | 0.27% | -2.8%
-| `bidirectional/4096` | asio (coroutines) | 1.06 GB/s | 0.45% | -4.3%
-| `bidirectional/4096` | asio (callbacks) | 1.10 GB/s | 0.36% | baseline
-| `bidirectional/65536` | corosio (IOCP) | 9.04 GB/s | 0.94% | -2.6%
-| `bidirectional/65536` | asio (coroutines) | 9.00 GB/s | 2.37% | -3.0%
-| `bidirectional/65536` | asio (callbacks) | 9.28 GB/s | 0.96% | baseline
-| `bidirectional_lockless/1024` | corosio (IOCP) | 279.6 MB/s | 0.44% | -2.9%
-| `bidirectional_lockless/1024` | asio (coroutines) | 274.6 MB/s | 0.65% | -4.6%
-| `bidirectional_lockless/1024` | asio (callbacks) | 287.9 MB/s | 0.49% | baseline
-| `bidirectional_lockless/1048576` | corosio (IOCP) | 4.69 GB/s | 7.57% | -1.5%
-| `bidirectional_lockless/1048576` | asio (coroutines) | 4.61 GB/s | 7.67% | -3.1%
-| `bidirectional_lockless/1048576` | asio (callbacks) | 4.76 GB/s | 8.69% | baseline
-| `bidirectional_lockless/16384` | corosio (IOCP) | 3.72 GB/s | 0.85% | -1.8%
-| `bidirectional_lockless/16384` | asio (coroutines) | 3.68 GB/s | 0.61% | -3.0%
-| `bidirectional_lockless/16384` | asio (callbacks) | 3.79 GB/s | 0.23% | baseline
-| `bidirectional_lockless/262144` | corosio (IOCP) | 9.76 GB/s | 1.34% | -0.1%
-| `bidirectional_lockless/262144` | asio (coroutines) | 9.71 GB/s | 0.99% | -0.6%
-| `bidirectional_lockless/262144` | asio (callbacks) | 9.76 GB/s | 1.25% | baseline
-| `bidirectional_lockless/4096` | corosio (IOCP) | 1.07 GB/s | 0.29% | -3.0%
-| `bidirectional_lockless/4096` | asio (coroutines) | 1.06 GB/s | 0.52% | -4.6%
-| `bidirectional_lockless/4096` | asio (callbacks) | 1.11 GB/s | 0.47% | baseline
-| `bidirectional_lockless/65536` | corosio (IOCP) | 8.91 GB/s | 1.43% | -2.0%
-| `bidirectional_lockless/65536` | asio (coroutines) | 8.85 GB/s | 0.38% | -2.7%
-| `bidirectional_lockless/65536` | asio (callbacks) | 9.09 GB/s | 0.19% | baseline
+| `bidirectional/1024` | corosio (IOCP) | 276.9 MB/s | 0.42% | -4.4%
+| `bidirectional/1024` | asio (coroutines) | 277.0 MB/s | 0.41% | -4.4%
+| `bidirectional/1024` | asio (callbacks) | 289.7 MB/s | 0.56% | baseline
+| `bidirectional/1048576` | corosio (IOCP) | 4.73 GB/s | 7.36% | -4.0%
+| `bidirectional/1048576` | asio (coroutines) | 4.99 GB/s | 8.67% | +1.3%
+| `bidirectional/1048576` | asio (callbacks) | 4.92 GB/s | 6.03% | baseline
+| `bidirectional/16384` | corosio (IOCP) | 3.71 GB/s | 0.54% | -3.6%
+| `bidirectional/16384` | asio (coroutines) | 3.66 GB/s | 2.25% | -4.9%
+| `bidirectional/16384` | asio (callbacks) | 3.84 GB/s | 0.71% | baseline
+| `bidirectional/262144` | corosio (IOCP) | 9.57 GB/s | 1.10% | +0.1%
+| `bidirectional/262144` | asio (coroutines) | 9.44 GB/s | 6.09% | -1.2%
+| `bidirectional/262144` | asio (callbacks) | 9.56 GB/s | 0.46% | baseline
+| `bidirectional/4096` | corosio (IOCP) | 1.06 GB/s | 0.55% | -4.1%
+| `bidirectional/4096` | asio (coroutines) | 1.06 GB/s | 0.77% | -4.1%
+| `bidirectional/4096` | asio (callbacks) | 1.11 GB/s | 0.39% | baseline
+| `bidirectional/65536` | corosio (IOCP) | 9.05 GB/s | 0.77% | -3.4%
+| `bidirectional/65536` | asio (coroutines) | 8.82 GB/s | 6.83% | -5.7%
+| `bidirectional/65536` | asio (callbacks) | 9.36 GB/s | 0.89% | baseline
+| `bidirectional_lockless/1024` | corosio (IOCP) | 276.4 MB/s | 0.46% | -4.4%
+| `bidirectional_lockless/1024` | asio (coroutines) | 277.2 MB/s | 0.66% | -4.1%
+| `bidirectional_lockless/1024` | asio (callbacks) | 289.1 MB/s | 0.60% | baseline
+| `bidirectional_lockless/1048576` | corosio (IOCP) | 5.15 GB/s | 8.88% | -2.2%
+| `bidirectional_lockless/1048576` | asio (coroutines) | 4.99 GB/s | 7.37% | -5.2%
+| `bidirectional_lockless/1048576` | asio (callbacks) | 5.27 GB/s | 7.80% | baseline
+| `bidirectional_lockless/16384` | corosio (IOCP) | 3.67 GB/s | 0.76% | -3.8%
+| `bidirectional_lockless/16384` | asio (coroutines) | 3.66 GB/s | 2.83% | -4.0%
+| `bidirectional_lockless/16384` | asio (callbacks) | 3.82 GB/s | 0.60% | baseline
+| `bidirectional_lockless/262144` | corosio (IOCP) | 9.63 GB/s | 1.70% | -2.2%
+| `bidirectional_lockless/262144` | asio (coroutines) | 9.70 GB/s | 1.16% | -1.5%
+| `bidirectional_lockless/262144` | asio (callbacks) | 9.85 GB/s | 0.90% | baseline
+| `bidirectional_lockless/4096` | corosio (IOCP) | 1.06 GB/s | 0.15% | -4.3%
+| `bidirectional_lockless/4096` | asio (coroutines) | 1.06 GB/s | 0.34% | -4.2%
+| `bidirectional_lockless/4096` | asio (callbacks) | 1.11 GB/s | 0.14% | baseline
+| `bidirectional_lockless/65536` | corosio (IOCP) | 8.95 GB/s | 1.02% | -2.0%
+| `bidirectional_lockless/65536` | asio (coroutines) | 8.82 GB/s | 0.55% | -3.4%
+| `bidirectional_lockless/65536` | asio (callbacks) | 9.13 GB/s | 1.12% | baseline
|===
====
@@ -359,15 +359,15 @@ image::bench/windows-socket_throughput-g2.svg[socket throughput comparison, part
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `multithread/2` | corosio (IOCP) | 12.68 GB/s | 0.54% | -2.1%
-| `multithread/2` | asio (coroutines) | 12.73 GB/s | 0.28% | -1.8%
-| `multithread/2` | asio (callbacks) | 12.96 GB/s | 0.37% | baseline
-| `multithread/4` | corosio (IOCP) | 17.09 GB/s | 0.54% | -2.7%
-| `multithread/4` | asio (coroutines) | 17.06 GB/s | 0.77% | -2.8%
-| `multithread/4` | asio (callbacks) | 17.56 GB/s | 0.45% | baseline
-| `multithread/8` | corosio (IOCP) | 18.40 GB/s | 0.37% | -0.4%
-| `multithread/8` | asio (coroutines) | 18.38 GB/s | 0.98% | -0.6%
-| `multithread/8` | asio (callbacks) | 18.48 GB/s | 1.82% | baseline
+| `multithread/2` | corosio (IOCP) | 12.67 GB/s | 0.71% | -2.1%
+| `multithread/2` | asio (coroutines) | 12.71 GB/s | 0.62% | -1.8%
+| `multithread/2` | asio (callbacks) | 12.95 GB/s | 0.58% | baseline
+| `multithread/4` | corosio (IOCP) | 16.98 GB/s | 0.79% | -2.3%
+| `multithread/4` | asio (coroutines) | 17.10 GB/s | 0.53% | -1.6%
+| `multithread/4` | asio (callbacks) | 17.38 GB/s | 0.42% | baseline
+| `multithread/8` | corosio (IOCP) | 18.31 GB/s | 0.69% | -1.6%
+| `multithread/8` | asio (coroutines) | 18.47 GB/s | 0.80% | -0.7%
+| `multithread/8` | asio (callbacks) | 18.61 GB/s | 2.34% | baseline
|===
====
@@ -383,42 +383,42 @@ image::bench/windows-socket_throughput-g3.svg[socket throughput comparison, part
[%autowidth.stretch,options="header"]
|===
| Benchmark | Implementation | Median | CV | vs asio
-| `unidirectional/1024` | corosio (IOCP) | 283.5 MB/s | 0.40% | -2.7%
-| `unidirectional/1024` | asio (coroutines) | 279.4 MB/s | 0.56% | -4.1%
-| `unidirectional/1024` | asio (callbacks) | 291.4 MB/s | 0.32% | baseline
-| `unidirectional/1048576` | corosio (IOCP) | 3.93 GB/s | 3.90% | +0.5%
-| `unidirectional/1048576` | asio (coroutines) | 3.94 GB/s | 2.24% | +0.6%
-| `unidirectional/1048576` | asio (callbacks) | 3.91 GB/s | 5.15% | baseline
-| `unidirectional/16384` | corosio (IOCP) | 3.78 GB/s | 1.35% | -2.3%
-| `unidirectional/16384` | asio (coroutines) | 3.73 GB/s | 0.73% | -3.5%
-| `unidirectional/16384` | asio (callbacks) | 3.87 GB/s | 0.66% | baseline
-| `unidirectional/262144` | corosio (IOCP) | 8.75 GB/s | 7.22% | -1.2%
-| `unidirectional/262144` | asio (coroutines) | 8.54 GB/s | 4.50% | -3.6%
-| `unidirectional/262144` | asio (callbacks) | 8.86 GB/s | 3.82% | baseline
-| `unidirectional/4096` | corosio (IOCP) | 1.09 GB/s | 0.43% | -2.5%
-| `unidirectional/4096` | asio (coroutines) | 1.07 GB/s | 0.12% | -4.0%
-| `unidirectional/4096` | asio (callbacks) | 1.12 GB/s | 0.44% | baseline
-| `unidirectional/65536` | corosio (IOCP) | 9.27 GB/s | 3.59% | -1.9%
-| `unidirectional/65536` | asio (coroutines) | 9.23 GB/s | 1.69% | -2.4%
-| `unidirectional/65536` | asio (callbacks) | 9.45 GB/s | 1.78% | baseline
-| `unidirectional_lockless/1024` | corosio (IOCP) | 282.6 MB/s | 0.33% | -2.6%
-| `unidirectional_lockless/1024` | asio (coroutines) | 279.3 MB/s | 0.50% | -3.8%
-| `unidirectional_lockless/1024` | asio (callbacks) | 290.2 MB/s | 0.42% | baseline
-| `unidirectional_lockless/1048576` | corosio (IOCP) | 4.37 GB/s | 4.83% | +1.7%
-| `unidirectional_lockless/1048576` | asio (coroutines) | 4.29 GB/s | 3.21% | -0.1%
-| `unidirectional_lockless/1048576` | asio (callbacks) | 4.30 GB/s | 7.83% | baseline
-| `unidirectional_lockless/16384` | corosio (IOCP) | 3.78 GB/s | 0.69% | -2.7%
-| `unidirectional_lockless/16384` | asio (coroutines) | 3.72 GB/s | 0.87% | -4.1%
-| `unidirectional_lockless/16384` | asio (callbacks) | 3.88 GB/s | 0.75% | baseline
-| `unidirectional_lockless/262144` | corosio (IOCP) | 9.77 GB/s | 1.43% | -0.7%
-| `unidirectional_lockless/262144` | asio (coroutines) | 9.76 GB/s | 0.85% | -0.8%
-| `unidirectional_lockless/262144` | asio (callbacks) | 9.84 GB/s | 1.23% | baseline
-| `unidirectional_lockless/4096` | corosio (IOCP) | 1.09 GB/s | 0.35% | -2.4%
-| `unidirectional_lockless/4096` | asio (coroutines) | 1.07 GB/s | 0.30% | -3.9%
-| `unidirectional_lockless/4096` | asio (callbacks) | 1.12 GB/s | 0.24% | baseline
-| `unidirectional_lockless/65536` | corosio (IOCP) | 9.35 GB/s | 2.30% | -1.8%
-| `unidirectional_lockless/65536` | asio (coroutines) | 9.26 GB/s | 1.66% | -2.8%
-| `unidirectional_lockless/65536` | asio (callbacks) | 9.52 GB/s | 0.82% | baseline
+| `unidirectional/1024` | corosio (IOCP) | 280.4 MB/s | 0.34% | -4.4%
+| `unidirectional/1024` | asio (coroutines) | 280.1 MB/s | 0.53% | -4.5%
+| `unidirectional/1024` | asio (callbacks) | 293.2 MB/s | 0.63% | baseline
+| `unidirectional/1048576` | corosio (IOCP) | 3.99 GB/s | 3.79% | +1.3%
+| `unidirectional/1048576` | asio (coroutines) | 4.12 GB/s | 4.17% | +4.6%
+| `unidirectional/1048576` | asio (callbacks) | 3.94 GB/s | 6.07% | baseline
+| `unidirectional/16384` | corosio (IOCP) | 3.76 GB/s | 0.49% | -3.1%
+| `unidirectional/16384` | asio (coroutines) | 3.71 GB/s | 4.56% | -4.5%
+| `unidirectional/16384` | asio (callbacks) | 3.88 GB/s | 4.63% | baseline
+| `unidirectional/262144` | corosio (IOCP) | 8.67 GB/s | 8.74% | +0.3%
+| `unidirectional/262144` | asio (coroutines) | 8.75 GB/s | 8.82% | +1.2%
+| `unidirectional/262144` | asio (callbacks) | 8.64 GB/s | 11.56% | baseline
+| `unidirectional/4096` | corosio (IOCP) | 1.08 GB/s | 0.23% | -3.9%
+| `unidirectional/4096` | asio (coroutines) | 1.07 GB/s | 1.42% | -4.5%
+| `unidirectional/4096` | asio (callbacks) | 1.12 GB/s | 1.21% | baseline
+| `unidirectional/65536` | corosio (IOCP) | 9.27 GB/s | 9.62% | -2.4%
+| `unidirectional/65536` | asio (coroutines) | 9.10 GB/s | 10.33% | -4.1%
+| `unidirectional/65536` | asio (callbacks) | 9.49 GB/s | 10.55% | baseline
+| `unidirectional_lockless/1024` | corosio (IOCP) | 281.0 MB/s | 0.25% | -3.7%
+| `unidirectional_lockless/1024` | asio (coroutines) | 279.6 MB/s | 0.68% | -4.2%
+| `unidirectional_lockless/1024` | asio (callbacks) | 291.8 MB/s | 0.48% | baseline
+| `unidirectional_lockless/1048576` | corosio (IOCP) | 4.30 GB/s | 4.37% | -4.4%
+| `unidirectional_lockless/1048576` | asio (coroutines) | 4.60 GB/s | 8.61% | +2.2%
+| `unidirectional_lockless/1048576` | asio (callbacks) | 4.50 GB/s | 7.74% | baseline
+| `unidirectional_lockless/16384` | corosio (IOCP) | 3.76 GB/s | 1.21% | -2.7%
+| `unidirectional_lockless/16384` | asio (coroutines) | 3.75 GB/s | 1.08% | -3.1%
+| `unidirectional_lockless/16384` | asio (callbacks) | 3.87 GB/s | 4.56% | baseline
+| `unidirectional_lockless/262144` | corosio (IOCP) | 9.77 GB/s | 1.59% | -0.8%
+| `unidirectional_lockless/262144` | asio (coroutines) | 9.68 GB/s | 3.04% | -1.7%
+| `unidirectional_lockless/262144` | asio (callbacks) | 9.85 GB/s | 3.53% | baseline
+| `unidirectional_lockless/4096` | corosio (IOCP) | 1.08 GB/s | 0.56% | -4.0%
+| `unidirectional_lockless/4096` | asio (coroutines) | 1.08 GB/s | 0.59% | -3.9%
+| `unidirectional_lockless/4096` | asio (callbacks) | 1.12 GB/s | 1.06% | baseline
+| `unidirectional_lockless/65536` | corosio (IOCP) | 9.31 GB/s | 3.43% | -2.2%
+| `unidirectional_lockless/65536` | asio (coroutines) | 9.00 GB/s | 2.20% | -5.4%
+| `unidirectional_lockless/65536` | asio (callbacks) | 9.52 GB/s | 10.70% | baseline
|===
====