From e98091e29859ee6a784ee6920048837f2b4536c2 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Wed, 7 Dec 2022 12:53:59 -0600 Subject: DRTVWR-559: Try using custom fiber scheduler for ThreadPool threads. (#30) Co-authored-by: Nat Goodspeed --- indra/llcommon/threadpool.cpp | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'indra/llcommon/threadpool.cpp') diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp index f49dd40a8b..b0d2016be0 100644 --- a/indra/llcommon/threadpool.cpp +++ b/indra/llcommon/threadpool.cpp @@ -23,6 +23,37 @@ #include "llsd.h" #include "stringize.h" +#include + +/***************************************************************************** +* Custom fiber scheduler for worker threads +*****************************************************************************/ +// As of 2022-12-06, each of our worker threads only runs a single (default) +// fiber: we don't launch explicit fibers within worker threads, nor do we +// anticipate doing so. So a worker thread that's simply waiting for incoming +// tasks should really sleep a little. Override the default fiber scheduler to +// implement that. +struct sleepy_robin: public boost::fibers::algo::round_robin +{ + virtual void suspend_until( std::chrono::steady_clock::time_point const&) noexcept + { + // round_robin holds a std::condition_variable, and + // round_robin::suspend_until() calls + // std::condition_variable::wait_until(). On Windows, that call seems + // busier than it ought to be. Try just sleeping. + Sleep(1); + } + + virtual void notify() noexcept + { + // Since our Sleep() call above will wake up on its own, we need not + // take any special action to wake it. + } +}; + +/***************************************************************************** +* ThreadPool +*****************************************************************************/ LL::ThreadPool::ThreadPool(const std::string& name, size_t threads, size_t capacity): super(name), mQueue(name, capacity), @@ -80,6 +111,11 @@ void LL::ThreadPool::close() void LL::ThreadPool::run(const std::string& name) { +#if LL_WINDOWS + // Try using sleepy_robin fiber scheduler. + boost::fibers::use_scheduling_algorithm(); +#endif // LL_WINDOWS + LL_DEBUGS("ThreadPool") << name << " starting" << LL_ENDL; run(); LL_DEBUGS("ThreadPool") << name << " stopping" << LL_ENDL; -- cgit v1.2.3 From e3b34fec6962e6deda3dd9dd83bf9fa20ab594af Mon Sep 17 00:00:00 2001 From: Brad Kittenbrink Date: Thu, 8 Dec 2022 12:53:51 -0800 Subject: Fix for non-windows build of DRTVWR-559 use usleep() for sleepy_robin scheduler --- indra/llcommon/threadpool.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'indra/llcommon/threadpool.cpp') diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp index b0d2016be0..1b29b8b69f 100644 --- a/indra/llcommon/threadpool.cpp +++ b/indra/llcommon/threadpool.cpp @@ -37,11 +37,17 @@ struct sleepy_robin: public boost::fibers::algo::round_robin { virtual void suspend_until( std::chrono::steady_clock::time_point const&) noexcept { +#if LL_WINDOWS // round_robin holds a std::condition_variable, and // round_robin::suspend_until() calls // std::condition_variable::wait_until(). On Windows, that call seems // busier than it ought to be. Try just sleeping. Sleep(1); +#else + // currently unused other than windows, but might as well have something here + // different units than Sleep(), but we actually just want to sleep for any de-minimis duration + usleep(1); +#endif } virtual void notify() noexcept -- cgit v1.2.3