From 69fb77246eeed41b4c40297cd301c5d48d3153b2 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 23 Oct 2023 18:48:02 +0200 Subject: [PATCH] Scheduler: implement capacity redistribution scheme wow... that was conceptually challenging, yet dead easy to implement --- src/vault/gear/load-controller.hpp | 32 ++++--- src/vault/gear/scheduler.hpp | 4 +- .../gear/scheduler-load-control-test.cpp | 94 ++++++++++++++++--- wiki/thinkPad.ichthyo.mm | 68 +++++++++++--- 4 files changed, 161 insertions(+), 37 deletions(-) diff --git a/src/vault/gear/load-controller.hpp b/src/vault/gear/load-controller.hpp index 14a977e47..8ffe680d5 100644 --- a/src/vault/gear/load-controller.hpp +++ b/src/vault/gear/load-controller.hpp @@ -169,7 +169,7 @@ namespace gear { /** classification of time horizon for scheduling */ static Capacity - classifyCapacity (Offset off) + classifyTimeHorizon (Offset off) { if (off > SLEEP_HORIZON) return IDLETIME; if (off > WORK_HORIZON) return WORKTIME; @@ -179,23 +179,29 @@ namespace gear { } + Capacity + markOutgoingCapacity (Time head, Time now) + { + auto horizon = classifyTimeHorizon (Offset{head - now}); + return horizon > SPINTIME + and not tendedNext(head)? TENDNEXT + : horizon; + } + + Capacity + markIncomingCapacity (Time head, Time now) + { + return classifyTimeHorizon (Offset{head - now}) + > NEARTIME ? IDLETIME + : markOutgoingCapacity(head,now); + } + + Time scatteredDelayTime (Capacity capacity) { UNIMPLEMENTED ("establish a randomised targeted delay time"); } - - Capacity - incomingCapacity (Time head, Time now) - { - UNIMPLEMENTED ("decide how to use incoming free work capacity"); - } - - Capacity - outgoingCapacity (Time head, Time now) - { - UNIMPLEMENTED ("decide how to use outgoing free work capacity"); - } }; diff --git a/src/vault/gear/scheduler.hpp b/src/vault/gear/scheduler.hpp index a306d95a6..cadc0d097 100644 --- a/src/vault/gear/scheduler.hpp +++ b/src/vault/gear/scheduler.hpp @@ -308,14 +308,14 @@ namespace gear { return WorkerInstruction{} .performStep([&]{ return scatteredDelay( - loadControl_.incomingCapacity (head,now)); + loadControl_.markIncomingCapacity (head,now)); }) .performStep([&]{ Activity* act = layer2_.findWork (layer1_,now); return ctx.post (now, act, ctx); }) .performStep([&]{ return scatteredDelay( - loadControl_.outgoingCapacity (head,now)); + loadControl_.markOutgoingCapacity (head,now)); }) ; } diff --git a/tests/vault/gear/scheduler-load-control-test.cpp b/tests/vault/gear/scheduler-load-control-test.cpp index b131e38e7..6d55860e3 100644 --- a/tests/vault/gear/scheduler-load-control-test.cpp +++ b/tests/vault/gear/scheduler-load-control-test.cpp @@ -64,8 +64,9 @@ namespace test { run (Arg) { simpleUsage(); - classifyTimings(); + classifyHorizon(); tendNextActivity(); + classifyCapacity(); walkingDeadline(); setupLalup(); } @@ -93,7 +94,7 @@ namespace test { * @todo WIP 10/23 ✔ define ⟶ ✔ implement */ void - classifyTimings() + classifyHorizon() { Time next{0,10}; @@ -105,16 +106,16 @@ namespace test { 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::IDLETIME == LoadController::classifyTimeHorizon (Offset{next - ut })); + CHECK (Capacity::IDLETIME == LoadController::classifyTimeHorizon (Offset{next - t1 })); + CHECK (Capacity::WORKTIME == LoadController::classifyTimeHorizon (Offset{next - t2 })); + CHECK (Capacity::WORKTIME == LoadController::classifyTimeHorizon (Offset{next - t21})); + CHECK (Capacity::NEARTIME == LoadController::classifyTimeHorizon (Offset{next - t3 })); + CHECK (Capacity::NEARTIME == LoadController::classifyTimeHorizon (Offset{next - t31})); + CHECK (Capacity::SPINTIME == LoadController::classifyTimeHorizon (Offset{next - t4 })); - CHECK (Capacity::DISPATCH == LoadController::classifyCapacity (Offset::ZERO )); - CHECK (Capacity::DISPATCH == LoadController::classifyCapacity (Offset{t4 - next })); + CHECK (Capacity::DISPATCH == LoadController::classifyTimeHorizon (Offset::ZERO )); + CHECK (Capacity::DISPATCH == LoadController::classifyTimeHorizon (Offset{t4 - next })); } @@ -159,6 +160,77 @@ namespace test { + /** @test verify allocation decision for free capacity + * - due and overdue Activities are prioritised + * - keep spinning when next Activity to schedule is very close + * - otherwise, priority is to tend for the next known Activity + * - beyond that, free capacity is redistributed according to horizon + * - for incoming free capacity there is a preference to keep it sleeping, + * to allow for disposing of excess capacity after extended sleep time + * @todo WIP 10/23 ✔ define ⟶ ✔ implement + */ + void + classifyCapacity() + { + BlockFlowAlloc bFlow; + LoadController lctrl{bFlow}; + + Time next{0,10}; + + Time ut{1,0}; + Time t1{0,9}; + Time t2{next - SLEEP_HORIZON}; + Time t3{next - WORK_HORIZON}; + Time t4{next - NOW_HORIZON}; + Time t5{next + ut}; // ╭────────────── next Activity at scheduler head + // │ ╭──────── current time of evaluation + // Time `next` has not been tended yet... // ▼ ▼ + CHECK (Capacity::TENDNEXT == lctrl.markOutgoingCapacity (next, ut )); + + // but after marking `next` as tended, capacity can be directed elsewhere + lctrl.tendNext (next); + CHECK (Capacity::IDLETIME == lctrl.markOutgoingCapacity (next, ut )); + + CHECK (Capacity::IDLETIME == lctrl.markOutgoingCapacity (next, t1 )); + CHECK (Capacity::WORKTIME == lctrl.markOutgoingCapacity (next, t2 )); + CHECK (Capacity::NEARTIME == lctrl.markOutgoingCapacity (next, t3 )); + CHECK (Capacity::SPINTIME == lctrl.markOutgoingCapacity (next, t4 )); + + CHECK (Capacity::DISPATCH == lctrl.markOutgoingCapacity (next,next)); + CHECK (Capacity::DISPATCH == lctrl.markOutgoingCapacity (next, t5 )); + + CHECK (Capacity::IDLETIME == lctrl.markIncomingCapacity (next, ut )); + CHECK (Capacity::IDLETIME == lctrl.markIncomingCapacity (next, t1 )); + CHECK (Capacity::IDLETIME == lctrl.markIncomingCapacity (next, t2 )); + CHECK (Capacity::NEARTIME == lctrl.markIncomingCapacity (next, t3 )); + CHECK (Capacity::SPINTIME == lctrl.markIncomingCapacity (next, t4 )); + + CHECK (Capacity::DISPATCH == lctrl.markIncomingCapacity (next,next)); + CHECK (Capacity::DISPATCH == lctrl.markIncomingCapacity (next, t5 )); + + // tend-next works in limited ways also on incoming capacity + lctrl.tendNext (Time::NEVER); + CHECK (Capacity::IDLETIME == lctrl.markIncomingCapacity (next, ut )); + CHECK (Capacity::IDLETIME == lctrl.markIncomingCapacity (next, t1 )); + CHECK (Capacity::IDLETIME == lctrl.markIncomingCapacity (next, t2 )); + CHECK (Capacity::TENDNEXT == lctrl.markIncomingCapacity (next, t3 )); + CHECK (Capacity::SPINTIME == lctrl.markIncomingCapacity (next, t4 )); + + CHECK (Capacity::DISPATCH == lctrl.markIncomingCapacity (next,next)); + CHECK (Capacity::DISPATCH == lctrl.markIncomingCapacity (next, t5 )); + + // while being used rather generously on outgoing capacity + CHECK (Capacity::TENDNEXT == lctrl.markOutgoingCapacity (next, ut )); + CHECK (Capacity::TENDNEXT == lctrl.markOutgoingCapacity (next, t1 )); + CHECK (Capacity::TENDNEXT == lctrl.markOutgoingCapacity (next, t2 )); + CHECK (Capacity::TENDNEXT == lctrl.markOutgoingCapacity (next, t3 )); + CHECK (Capacity::SPINTIME == lctrl.markOutgoingCapacity (next, t4 )); + + CHECK (Capacity::DISPATCH == lctrl.markOutgoingCapacity (next,next)); + CHECK (Capacity::DISPATCH == lctrl.markOutgoingCapacity (next, t5 )); + } + + /** @test TODO * @todo WIP 10/23 🔁 define ⟶ implement */ diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 495994ff6..734e02bd1 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -82004,9 +82004,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - + @@ -82256,7 +82256,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + @@ -82283,6 +82285,11 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + @@ -82500,7 +82507,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + @@ -82609,20 +82618,44 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -82632,6 +82665,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + @@ -91094,6 +91134,12 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + +