Scheduler: implement capacity redistribution scheme

wow... that was conceptually challenging, yet dead easy to implement
This commit is contained in:
Fischlurch 2023-10-23 18:48:02 +02:00
parent 6ccb6540e6
commit 69fb77246e
4 changed files with 161 additions and 37 deletions

View file

@ -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");
}
};

View file

@ -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));
})
;
}

View file

@ -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
*/

View file

@ -82004,9 +82004,9 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697768205409" ID="ID_489957180" MODIFIED="1697768215224" TEXT="mit dem Load-Controller verbinden">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697808041495" ID="ID_492054934" MODIFIED="1698004006239" TEXT="die Work-Function zusammenstellen">
<node COLOR="#338800" CREATED="1697808041495" ID="ID_492054934" MODIFIED="1698079204212" TEXT="die Work-Function zusammenstellen">
<linktarget COLOR="#7779a3" DESTINATION="ID_492054934" ENDARROW="Default" ENDINCLINATION="-814;62;" ID="Arrow_ID_817672667" SOURCE="ID_391492289" STARTARROW="None" STARTINCLINATION="1393;-112;"/>
<icon BUILTIN="flag-yellow"/>
<icon BUILTIN="button_ok"/>
<node CREATED="1698004010478" ID="ID_1609383346" MODIFIED="1698009701573" TEXT="Schritte">
<icon BUILTIN="list"/>
<node CREATED="1698004022584" ID="ID_1953987297" MODIFIED="1698009688618" TEXT="Kapazit&#xe4;t feststellen">
@ -82256,7 +82256,9 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node CREATED="1697934020751" ID="ID_1139695361" MODIFIED="1697934032818" TEXT="wenn nichts mehr passiert, kann er sich deaktivieren">
<node CREATED="1697935611257" ID="ID_436115424" MODIFIED="1697935652768" TEXT="zun&#xe4;chst werden die Worker schlafen geschickt">
<node CREATED="1697935685080" ID="ID_1125666331" MODIFIED="1697935700776" TEXT="Vorsicht: vorausschauend handeln"/>
<node CREATED="1697935685080" ID="ID_1125666331" MODIFIED="1698079245795" TEXT="Vorsicht: vorausschauend handeln">
<icon BUILTIN="yes"/>
</node>
<node CREATED="1697935701613" ID="ID_601914515" MODIFIED="1697935798105" TEXT="der Schlaf-Zyklus soll relativ lang sein">
<richcontent TYPE="NOTE"><html>
<head/>
@ -82283,6 +82285,11 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node CREATED="1697939007756" ID="ID_1814410393" MODIFIED="1697939068200" TEXT="idle-Time &#x27f6; schlafen schicken"/>
</node>
<node CREATED="1698079285650" ID="ID_1194794962" MODIFIED="1698079299495" TEXT="freie Kapazit&#xe4;t &#x201e;flie&#xdf;t&#x201c;">
<node CREATED="1698079326197" ID="ID_1517718994" MODIFIED="1698079334136" TEXT="ein Teil setzt sich ab"/>
<node CREATED="1698079334681" ID="ID_1880078243" MODIFIED="1698079345414" TEXT="aber auch von den Schl&#xe4;fern gibt es einen R&#xfc;ckstrom"/>
<node CREATED="1698079346272" ID="ID_1708377480" MODIFIED="1698079371100" TEXT="Konzentration je nach Arbeitsdichte"/>
</node>
</node>
</node>
<node CREATED="1697935657451" ID="ID_1200603474" MODIFIED="1697935676437" TEXT="diese beenden sich dann nach einiger Zeit von selbst">
@ -82500,7 +82507,9 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="flag-yellow"/>
<node CREATED="1697982488254" ID="ID_1839282150" MODIFIED="1697982492138" TEXT="incomingCapacity"/>
<node CREATED="1697982492782" ID="ID_1050821331" MODIFIED="1697982497641" TEXT="outgoingCapacity"/>
<node CREATED="1697982575563" ID="ID_1770606344" MODIFIED="1697982580261" TEXT="dispatchedCapacity"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1697982575563" ID="ID_1770606344" MODIFIED="1698078325355" TEXT="dispatchedCapacity">
<icon BUILTIN="help"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697982589257" HGAP="11" ID="ID_1783139757" MODIFIED="1697982614929" TEXT="pro-forma in den LoadController legen" VSHIFT="9">
<icon BUILTIN="yes"/>
</node>
@ -82609,20 +82618,44 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1697983591252" ID="ID_777679840" MODIFIED="1697983596782" TEXT="liefert activity::PROC"/>
<node CREATED="1697983597603" ID="ID_1430310887" MODIFIED="1697983605069" TEXT="f&#xfc;hrt die Verz&#xf6;gerung unmittelbar aus"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697983546449" ID="ID_1801117774" MODIFIED="1697983563416" TEXT="scatteredDelayTime()">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1697983546449" ID="ID_1801117774" MODIFIED="1698079545463" TEXT="scatteredDelayTime()">
<icon BUILTIN="forward"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1698003862646" ID="ID_402749835" MODIFIED="1698003871297" TEXT="Integration mit...">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1698003871908" ID="ID_391492289" MODIFIED="1698003962732" TEXT="work-Function">
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1698003871908" ID="ID_391492289" MODIFIED="1698079188892" TEXT="work-Function">
<arrowlink COLOR="#7779a3" DESTINATION="ID_492054934" ENDARROW="Default" ENDINCLINATION="-814;62;" ID="Arrow_ID_817672667" STARTARROW="None" STARTINCLINATION="1393;-112;"/>
<icon BUILTIN="flag-yellow"/>
<node CREATED="1698019149574" HGAP="40" ID="ID_982468485" MODIFIED="1698019158970" TEXT="Fallunterscheidung" VSHIFT="21">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1698019149574" HGAP="40" ID="ID_982468485" MODIFIED="1698078066168" TEXT="Fallunterscheidung" VSHIFT="21">
<linktarget COLOR="#378f79" DESTINATION="ID_982468485" ENDARROW="Default" ENDINCLINATION="-84;-47;" ID="Arrow_ID_902782295" SOURCE="ID_1677472042" STARTARROW="None" STARTINCLINATION="31;94;"/>
<node CREATED="1698019164588" ID="ID_1369255451" MODIFIED="1698019165160" TEXT="incomingCapacity"/>
<node CREATED="1698019170228" ID="ID_311501577" MODIFIED="1698019170871" TEXT="outgoingCapacity"/>
<icon BUILTIN="button_ok"/>
<node CREATED="1698019170228" ID="ID_311501577" MODIFIED="1698078071150" TEXT="outgoingCapacity">
<node CREATED="1698078074777" ID="ID_1807447539" MODIFIED="1698078181537" TEXT="Basis-Schema ">
<icon BUILTIN="info"/>
</node>
<node CREATED="1698078079896" ID="ID_608362501" MODIFIED="1698078184283" TEXT="f&#xe4;llige Termine haben Vorrang">
<icon BUILTIN="full-1"/>
</node>
<node CREATED="1698078093672" ID="ID_1701101602" MODIFIED="1698078186423" TEXT="im Nah-Intervall wird gespinnt">
<icon BUILTIN="full-2"/>
</node>
<node CREATED="1698078109744" ID="ID_865429598" MODIFIED="1698078188571" TEXT="tend-Next-Mechanismus">
<icon BUILTIN="full-3"/>
</node>
<node CREATED="1698078151042" ID="ID_558277791" MODIFIED="1698078191203" TEXT="Redistribution im Horizont">
<icon BUILTIN="full-4"/>
</node>
<node CREATED="1698078223097" ID="ID_597306541" MODIFIED="1698078227054" TEXT="Schlafen">
<icon BUILTIN="full-5"/>
</node>
</node>
<node CREATED="1698019164588" ID="ID_1369255451" MODIFIED="1698019165160" TEXT="incomingCapacity">
<node CREATED="1698078198356" ID="ID_187052761" MODIFIED="1698078221980" TEXT="Schlafen hat Vorrang"/>
<node CREATED="1698078230223" ID="ID_956821068" MODIFIED="1698078245813" TEXT="aber f&#xe4;llige Temine und Nach-Intervall werden bedient"/>
<node CREATED="1698078250230" ID="ID_69285927" MODIFIED="1698078267335" TEXT="tend-Next findet nur in NEARTIME statt"/>
</node>
</node>
</node>
</node>
@ -82632,6 +82665,13 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="pencil"/>
</node>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1698078367419" HGAP="-36" ID="ID_1532750540" MODIFIED="1698079050460" TEXT="offene Fragen" VSHIFT="11">
<linktarget COLOR="#713d56" DESTINATION="ID_1532750540" ENDARROW="Default" ENDINCLINATION="-2344;353;" ID="Arrow_ID_1939324405" SOURCE="ID_161990356" STARTARROW="None" STARTINCLINATION="1495;112;"/>
<icon BUILTIN="bell"/>
<node CREATED="1698078395346" ID="ID_1995310118" MODIFIED="1698078418081" TEXT="ist die probabilistische Kapazit&#xe4;tsverteilung ausreichend, um Aussetzer zu verhindern?"/>
<node CREATED="1698078423734" ID="ID_588175161" MODIFIED="1698078714099" TEXT="bringt das Spinning im Nah-Bereich &#xfc;berhaupt etwas (oder schadet es gar?)"/>
<node CREATED="1698078720726" ID="ID_690302845" MODIFIED="1698078865023" TEXT="mu&#xdf; incomingCapacity &#xfc;berhaupt am tend-Next teilnehmen?"/>
</node>
</node>
<node COLOR="#338800" CREATED="1687738213842" ID="ID_683259902" MODIFIED="1687738250423" TEXT="Payload: ActOrder">
<icon BUILTIN="button_ok"/>
@ -91094,6 +91134,12 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node CREATED="1698079023246" ID="ID_1404968698" MODIFIED="1698079027257" TEXT="Diskussion und Fragen">
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1698078896511" ID="ID_161990356" MODIFIED="1698079050460" TEXT="Fragen zum Scheduler Load-Control">
<arrowlink COLOR="#713d56" DESTINATION="ID_1532750540" ENDARROW="Default" ENDINCLINATION="-2344;353;" ID="Arrow_ID_1939324405" STARTARROW="None" STARTINCLINATION="1495;112;"/>
<icon BUILTIN="hourglass"/>
</node>
</node>
</node>
</node>
</node>