From 84ca2460c18c101000516922243ca26570fc8e96 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 23 Oct 2023 04:07:38 +0200 Subject: [PATCH] Scheduler: fundamentals of capacity classification Workers asking for the next task are classified as belonging to some fraction of the free capacity, based on the distance to the closest next Activity known to the scheduler --- src/vault/gear/load-controller.hpp | 70 +++++++++- src/vault/gear/scheduler.hpp | 4 + .../gear/scheduler-load-control-test.cpp | 45 +++++- wiki/thinkPad.ichthyo.mm | 132 +++++++++++++++++- 4 files changed, 236 insertions(+), 15 deletions(-) diff --git a/src/vault/gear/load-controller.hpp b/src/vault/gear/load-controller.hpp index e515f4393..e70d2f5f5 100644 --- a/src/vault/gear/load-controller.hpp +++ b/src/vault/gear/load-controller.hpp @@ -31,6 +31,39 @@ ** are designed to withstand a short-term imbalance, expecting that general ** engine parametrisation will be adjusted based on moving averages. ** + ** # Principles for Engine Load Control + ** + ** Scheduling and dispatch of Activities are driven by active workers invoking + ** the Scheduler-Service to retrieve the next piece of work. While this scheme + ** ensures that the scarce resource (computation or IO capacity) is directed + ** towards the most urgent next task, achieving a smooth operation of the engine + ** without wasted capacity requires additionally to control the request cycles + ** of the workers, possibly removing excess capacity. Whenever a worker pulls + ** the next task, an assessment of the timing situation is conducted, and the + ** worker is placed into some partition of the overall available capacity, + ** to reflect the current load and demand. Workers are thus moved between + ** the segments, preferring to assign work to workers already in the active + ** segment, thereby allowing idle workers to be shut down after some time. + ** + ** The key element to decide upon the classification of a worker is the current + ** scheduling situation: are some Activities overdue? does the next Activity + ** to be considered reach far into the future? If there is immediately imminent + ** work, then capacity is kept around; otherwise the capacity can be considered + ** to be in excess for now. A worker not required right now can be sent into a + ** targeted sleep delay, in order to shift its capacity into a zone where it + ** will more likely be required. It is essential to apply some randomisation + ** on such capacity shifts, in order to achieve an even distribution of free + ** capacity and avoid contention between workers asking for new assignments. + ** + ** When a worker becomes available and is not needed at the moment, the first + ** thing to check is the time of the next approaching Activity; this worker + ** can then be directed close to this next task, which thereby has been tended + ** for and can be marked accordingly. Any further worker appearing meanwhile + ** can then be directed into the time zone _after_ the next approaching task. + ** Workers immediately returning from active work are always preferred for + ** assigning new tasks, while workers returning from idle state are typically + ** sent back into idle state, unless there is direct need for more capacity. + ** ** @see scheduler.hpp ** @see SchedulerStress_test ** @@ -59,7 +92,27 @@ namespace gear { // using util::isnil; // using std::string; - using std::chrono::microseconds; + + using lib::time::Time; + using lib::time::FSecs; + using lib::time::Offset; + using lib::time::Duration; + using std::chrono_literals::operator ""ms; + using std::chrono_literals::operator ""us; + + namespace { // Scheduler default config + + inline TimeValue + _uTicks (std::chrono::microseconds us) + { + return TimeValue{us.count()}; + } + + + Duration SLEEP_HORIZON{_uTicks (20ms)}; + Duration WORK_HORIZON {_uTicks ( 5ms)}; + Duration NOW_HORIZON {_uTicks (50us)}; + } /** @@ -104,15 +157,20 @@ namespace gear { ,IDLETIME ///< time to go to sleep }; - Capacity - classifyCapacity() const + /** classification of time horizon for scheduling */ + static Capacity + classifyCapacity (Offset off) { - UNIMPLEMENTED ("establish a categorisation for available capacity"); + if (off > SLEEP_HORIZON) return IDLETIME; + if (off > WORK_HORIZON) return WORKTIME; + if (off > NOW_HORIZON) return NEARTIME; + if (off > Time::ZERO) return SPINTIME; + else return DISPATCH; } - microseconds - scatteredDelayTime() + Time + scatteredDelayTime (Capacity capacity) { UNIMPLEMENTED ("establish a randomised targeted delay time"); } diff --git a/src/vault/gear/scheduler.hpp b/src/vault/gear/scheduler.hpp index 490103d6d..a306d95a6 100644 --- a/src/vault/gear/scheduler.hpp +++ b/src/vault/gear/scheduler.hpp @@ -64,6 +64,10 @@ namespace gear { // using util::isnil; // using std::string; using std::move; + using lib::time::Time; + using lib::time::FSecs; + using lib::time::Offset; + using lib::time::Duration; namespace { // Scheduler default config diff --git a/tests/vault/gear/scheduler-load-control-test.cpp b/tests/vault/gear/scheduler-load-control-test.cpp index 003355b12..4d4a14abc 100644 --- a/tests/vault/gear/scheduler-load-control-test.cpp +++ b/tests/vault/gear/scheduler-load-control-test.cpp @@ -45,6 +45,7 @@ namespace test { // using lib::time::FrameRate; // using lib::time::Offset; // using lib::time::Time; + using Capacity = LoadController::Capacity; @@ -63,19 +64,59 @@ namespace test { run (Arg) { simpleUsage(); + classifyTimings(); walkingDeadline(); setupLalup(); } /** @test TODO demonstrate a simple usage scenario - * @todo WIP 10/23 ✔ define ⟶ 🔁 implement + * @todo WIP 10/23 🔁 define ⟶ 🔁 implement */ void simpleUsage() { BlockFlowAlloc bFlow; - LoadController lcontrl{bFlow}; + LoadController ctrl{bFlow}; + } + + + + /** @test verify classification of time horizon for scheduling. + * - if the next planned Activity lies beyond the SLEEP_HORIZON, + * then the current thread can be considered part of the _idle capacity_ + * - in a similar way, WORK_HORIZON delineates the zone of repeated incoming + * Activities from the zone considered part of current active operation + * - Activities within the NOW_HORIZON can be awaited by yield-spinning + * - and any event from current into the past will be scheduled right away + * @todo WIP 10/23 ✔ define ⟶ ✔ implement + */ + void + classifyTimings() + { + BlockFlowAlloc bFlow; + LoadController ctrl{bFlow}; + + Time next{0,10}; + + Time ut{1,0}; + Time t1{0,9}; + Time t2{next - SLEEP_HORIZON}; + Time t21{t2 + ut}; + Time t3{next - WORK_HORIZON}; + Time t31{t3 + ut}; + Time t4{next - NOW_HORIZON}; + + CHECK (Capacity::IDLETIME == LoadController::classifyCapacity (Offset{next - ut })); + CHECK (Capacity::IDLETIME == LoadController::classifyCapacity (Offset{next - t1 })); + CHECK (Capacity::WORKTIME == LoadController::classifyCapacity (Offset{next - t2 })); + CHECK (Capacity::WORKTIME == LoadController::classifyCapacity (Offset{next - t21})); + CHECK (Capacity::NEARTIME == LoadController::classifyCapacity (Offset{next - t3 })); + CHECK (Capacity::NEARTIME == LoadController::classifyCapacity (Offset{next - t31})); + CHECK (Capacity::SPINTIME == LoadController::classifyCapacity (Offset{next - t4 })); + + CHECK (Capacity::DISPATCH == LoadController::classifyCapacity (Offset::ZERO )); + CHECK (Capacity::DISPATCH == LoadController::classifyCapacity (Offset{t4 - next })); } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 2e4cd5341..c2f57bc88 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -81970,6 +81970,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + @@ -81991,6 +81994,11 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + @@ -82436,6 +82444,30 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + + + + + + +

+ ....denn dann kommen die periodischen Worker sofort zum Zug +

+ +
+
+
+
@@ -82483,13 +82515,95 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - - - - - + + + + + + + + + + +

+ sent to work +

+ + +
+
+ + + + + + +

+ reserved for next task +

+ + +
+
+ + + + + + +

+ awaiting imminent activities +

+ + +
+
+ + + + + + +

+ capacity for active processing required +

+ + +
+
+ + + + + + +

+ typical stable work task rhythm expected +

+ + +
+
+ + + + + + +

+ time to go to sleep +

+ + +
+
+
+ + + + + + @@ -82517,6 +82631,10 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + +