1111// I/O Read Stream Benchmark
1212//
1313// Compares three execution models across three stream abstraction
14- // levels. 100M read_some calls per cell, single thread.
14+ // levels. 20M read_some calls per cell, single thread.
1515//
1616// Table 1: sender pipeline (connect/start)
1717// Table 2: capy::task (capy::thread_pool)
2727#include " awaitable_sender.hpp"
2828#include " ioaw_read_stream.hpp"
2929#include " ioaw_io_read_stream.hpp"
30- #include " repeat_effect_until .hpp"
30+ #include " repeat_until .hpp"
3131#include " sender_awaitable.hpp"
3232#include " sndr_any_read_stream.hpp"
3333#include " sndr_io_read_stream.hpp"
@@ -248,12 +248,14 @@ int main()
248248 for (int run = 0 ; run <= NUM_RUNS; ++run)
249249 {
250250
251+
251252 // ---------------------------------------------------------------
252- // Table 1: sender/receiver pipeline (repeat_effect_until )
253+ // Table 1: sender/receiver pipeline (repeat_until )
253254 // ---------------------------------------------------------------
254255
255256 // Col A: Sender (native)
256257
258+
257259 // Native — sndr_read_stream
258260 {
259261 sender_thread_pool pool (1 );
@@ -265,7 +267,7 @@ int main()
265267 std::memory_order_relaxed);
266268 auto start = std::chrono::steady_clock::now ();
267269 bex::sync_wait (bex::starts_on (sched,
268- repeat_effect_until (
270+ repeat_until (
269271 bex::let_value (bex::just (), [&]() {
270272 return stream.read_some (
271273 capy::mutable_buffer (buf, sizeof (buf)));
@@ -293,7 +295,7 @@ int main()
293295 std::memory_order_relaxed);
294296 auto start = std::chrono::steady_clock::now ();
295297 bex::sync_wait (bex::starts_on (sched,
296- repeat_effect_until (
298+ repeat_until (
297299 bex::let_value (bex::just (), [&]() {
298300 return static_cast <sndr_io_read_stream&>(
299301 stream).read_some (
@@ -322,7 +324,7 @@ int main()
322324 std::memory_order_relaxed);
323325 auto start = std::chrono::steady_clock::now ();
324326 bex::sync_wait (bex::starts_on (sched,
325- repeat_effect_until (
327+ repeat_until (
326328 bex::let_value (bex::just (), [&]() {
327329 return stream.read_some (
328330 capy::mutable_buffer (buf, sizeof (buf)));
@@ -341,6 +343,7 @@ int main()
341343
342344 // Col B: Awaitable (via as_sender bridge)
343345
346+
344347 // Native — ioaw_read_stream
345348 {
346349 sender_thread_pool pool (1 );
@@ -352,7 +355,7 @@ int main()
352355 std::memory_order_relaxed);
353356 auto start = std::chrono::steady_clock::now ();
354357 bex::sync_wait (bex::starts_on (sched,
355- repeat_effect_until (
358+ repeat_until (
356359 bex::let_value (bex::just (), [&]() {
357360 return capy::as_sender (stream.read_some (
358361 capy::mutable_buffer (buf, sizeof (buf))));
@@ -380,7 +383,7 @@ int main()
380383 std::memory_order_relaxed);
381384 auto start = std::chrono::steady_clock::now ();
382385 bex::sync_wait (bex::starts_on (sched,
383- repeat_effect_until (
386+ repeat_until (
384387 bex::let_value (bex::just (), [&]() {
385388 return capy::as_sender (
386389 static_cast <ioaw_io_read_stream&>(
@@ -412,7 +415,7 @@ int main()
412415 std::memory_order_relaxed);
413416 auto start = std::chrono::steady_clock::now ();
414417 bex::sync_wait (bex::starts_on (sched,
415- repeat_effect_until (
418+ repeat_until (
416419 bex::let_value (bex::just (), [&]() {
417420 return capy::as_sender (stream.read_some (
418421 capy::mutable_buffer (buf, sizeof (buf))));
@@ -429,16 +432,68 @@ int main()
429432 after - before};
430433 }
431434
432- // Synchronous — sender pipeline cannot run synchronous
433- // senders. repeat_effect_until requires a trampoline for
434- // synchronous completions, and the trampoline interacts
435- // poorly with the let_value/starts_on sender layering.
436- // Table 1 SYNC_STREAM cells are left at zero.
435+
436+ // Synchronous — sndr_sync_read_stream (Col A)
437+ {
438+ sender_thread_pool pool (1 );
439+ sndr_sync_read_stream stream;
440+ auto sched = pool.get_scheduler ();
441+ int count = OPS_PER_CELL;
442+ char buf[64 ];
443+ auto before = g_alloc_count.load (
444+ std::memory_order_relaxed);
445+ auto start = std::chrono::steady_clock::now ();
446+ bex::sync_wait (bex::starts_on (sched,
447+ repeat_until (
448+ bex::let_value (bex::just (), [&]() {
449+ return stream.read_some (
450+ capy::mutable_buffer (buf, sizeof (buf)));
451+ }),
452+ [&count]() { return --count == 0 ; })));
453+ pool.join ();
454+ auto elapsed =
455+ std::chrono::steady_clock::now () - start;
456+ auto after = g_alloc_count.load (
457+ std::memory_order_relaxed);
458+ grid[run][SENDER_RECEIVER][SYNC_STREAM][NATIVE_EXEC_MODEL] = {
459+ std::chrono::duration_cast<
460+ std::chrono::nanoseconds>(elapsed).count (),
461+ after - before};
462+ }
463+
464+ // Synchronous — ioaw_sync_read_stream (Col B)
465+ {
466+ sender_thread_pool pool (1 );
467+ ioaw_sync_read_stream stream;
468+ auto sched = pool.get_scheduler ();
469+ int count = OPS_PER_CELL;
470+ char buf[64 ];
471+ auto before = g_alloc_count.load (
472+ std::memory_order_relaxed);
473+ auto start = std::chrono::steady_clock::now ();
474+ bex::sync_wait (bex::starts_on (sched,
475+ repeat_until (
476+ bex::let_value (bex::just (), [&]() {
477+ return capy::as_sender (stream.read_some (
478+ capy::mutable_buffer (buf, sizeof (buf))));
479+ }),
480+ [&count]() { return --count == 0 ; })));
481+ pool.join ();
482+ auto elapsed =
483+ std::chrono::steady_clock::now () - start;
484+ auto after = g_alloc_count.load (
485+ std::memory_order_relaxed);
486+ grid[run][SENDER_RECEIVER][SYNC_STREAM][BRIDGED_EXEC_MODEL] = {
487+ std::chrono::duration_cast<
488+ std::chrono::nanoseconds>(elapsed).count (),
489+ after - before};
490+ }
437491
438492 // ---------------------------------------------------------------
439493 // Table 2: capy::task (capy::thread_pool)
440494 // ---------------------------------------------------------------
441495
496+
442497 // Native — ioaw_read_stream
443498 {
444499 capy::thread_pool pool (1 );
@@ -525,6 +580,7 @@ int main()
525580 // Table 3: beman::execution::task (bex::task<void, io_env>)
526581 // ---------------------------------------------------------------
527582
583+
528584 // Native — sndr_read_stream
529585 {
530586 sender_thread_pool pool (1 );
@@ -676,18 +732,6 @@ int main()
676732
677733 for (int s = 0 ; s < NUM_STREAMS; ++s)
678734 {
679- if (s == SYNC_STREAM &&
680- table == SENDER_RECEIVER)
681- {
682- std::printf (
683- " %-18s"
684- " %-30s %-30s\n " ,
685- row_labels[s],
686- " N/A" ,
687- " N/A" );
688- continue ;
689- }
690-
691735 double sum[NUM_COLUMNS]{};
692736 double sum2[NUM_COLUMNS]{};
693737 double al[NUM_COLUMNS]{};
0 commit comments