From 5ea44519f3e51144861bc50f750c4d32c38b4b18 Mon Sep 17 00:00:00 2001 From: Florian Fischer <florian.fl.fischer@fau.de> Date: Tue, 23 Mar 2021 14:31:27 +0100 Subject: [PATCH] [IO] make the behavior of the completer thread configurable Available behaviors: * none - the completer thread is not started * schedule (default) - the completer thread will reap and schedule available completions from worker IoContexts * wakeup - the completer thread will wakeup all workers if it observes completions in a worker IoContext. The Fiber produced by the completion will be scheduled when the worker in which's IoContext the cqe lies reaps its completions. --- emper/Emper.hpp | 9 +++++++++ emper/Runtime.cpp | 10 +++++++--- emper/io/GlobalIoContext.cpp | 11 +++++++++-- meson.build | 10 ++++++++++ meson_options.txt | 7 +++++++ 5 files changed, 42 insertions(+), 5 deletions(-) diff --git a/emper/Emper.hpp b/emper/Emper.hpp index 2138be46..2bfbf49f 100644 --- a/emper/Emper.hpp +++ b/emper/Emper.hpp @@ -97,4 +97,13 @@ static const bool IO_URING_SHARED_WQ = false #endif ; + +enum class IoCompleterBehavior { + schedule, + wakeup, + none, +}; + +static const enum IoCompleterBehavior IO_COMPLETER_BEHAVIOR = + IoCompleterBehavior::EMPER_IO_COMPLETER_BEHAVIOR; } // namespace emper diff --git a/emper/Runtime.cpp b/emper/Runtime.cpp index 43ba9be7..e4b18974 100644 --- a/emper/Runtime.cpp +++ b/emper/Runtime.cpp @@ -92,7 +92,9 @@ Runtime::Runtime(workerid_t workerCount, RuntimeStrategyFactory& strategyFactory // for each worker's IoContext one eventfd read is prepared before the // globalCompleter is started and submits all previously prepared sqes. globalIo = new GlobalIoContext(*this, workerCount); - globalIo->startGlobalCompleter(); + if constexpr (emper::IO_COMPLETER_BEHAVIOR != emper::IoCompleterBehavior::none) { + globalIo->startGlobalCompleter(); + } if constexpr (emper::STATS) { globalIo->stats.workerId = -1; @@ -196,8 +198,10 @@ auto Runtime::workerLoop(Worker* worker) -> void* { if constexpr (emper::IO) { auto* workerIo = new IoContext(*this); - // submit the workers' CQ eventfds to the global IoContext - globalIo->registerWorkerIo(*workerIo); + if constexpr (emper::IO_COMPLETER_BEHAVIOR != emper::IoCompleterBehavior::none) { + // submit the workers' CQ eventfds to the global IoContext + globalIo->registerWorkerIo(*workerIo); + } // notify the globalCompleter that we have registered our eventfd ioReadySem.notify(); diff --git a/emper/io/GlobalIoContext.cpp b/emper/io/GlobalIoContext.cpp index 27b4b075..83799c78 100644 --- a/emper/io/GlobalIoContext.cpp +++ b/emper/io/GlobalIoContext.cpp @@ -14,6 +14,7 @@ #include "CallerEnvironment.hpp" #include "Common.hpp" +#include "Emper.hpp" #include "Runtime.hpp" #include "io/Future.hpp" #include "io/IoContext.hpp" @@ -82,7 +83,7 @@ auto GlobalIoContext::globalCompleterFunc(void* arg) -> void* { // -> there are completions on this worker IoContext switch (tag) { // clang-11 does not support [[likely]] yet - // TODO: remove the preprocessor check if clang ass [[likely]] support + // TODO: remove the preprocessor check if clang has [[likely]] support #if defined __has_attribute #if __has_attribute(likely) [[likely]] // NOLINT(clang-diagnostic-unknown-attributes) @@ -103,7 +104,13 @@ auto GlobalIoContext::globalCompleterFunc(void* arg) -> void* { assert(submitted == 1); - worker_io->reapAndScheduleCompletions<CallerEnvironment::ANYWHERE>(); + if constexpr (emper::IO_COMPLETER_BEHAVIOR == emper::IoCompleterBehavior::wakeup) { + // Only wakeup sleeping workers and hope that the worker which + // has ready cqes will reap them soon. + globalIoContext->runtime.wakeupSleepingWorkers<CallerEnvironment::ANYWHERE>(); + } else { + worker_io->reapAndScheduleCompletions<CallerEnvironment::ANYWHERE>(); + } } break; diff --git a/meson.build b/meson.build index 9a6bca81..276a7c4e 100644 --- a/meson.build +++ b/meson.build @@ -93,6 +93,16 @@ endforeach io_cq_lock_impl = get_option('io_cq_lock_implementation') conf_data.set('EMPER_IO_CQ_LOCK_' + io_cq_lock_impl.to_upper(), true) +io_completer_behavior = get_option('io_completer_behavior') +if io_completer_behavior == 'maybe_wakeup' + if get_option('worker_sleep') + io_completer_behavior = 'wakeup' + else + io_completer_behavior = 'none' + endif +endif +conf_data.set('EMPER_IO_COMPLETER_BEHAVIOR', io_completer_behavior) + subdir('emper') subdir('tests') subdir('apps') diff --git a/meson_options.txt b/meson_options.txt index 06bd0206..ac1f842c 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -122,3 +122,10 @@ option( choices: ['spin_lock', 'counting_try_lock', 'mutex'], value: 'counting_try_lock', ) +option( + 'io_completer_behavior', + type: 'combo', + description: 'The behaviour of the IO completer thread', + choices: ['schedule', 'maybe_wakeup'], + value: 'schedule', +) -- GitLab