Scheduler: control structure for the worker-functor

This commit is contained in:
Fischlurch 2023-10-22 23:25:35 +02:00
parent e5638119f5
commit a21057bdf2
4 changed files with 170 additions and 70 deletions

View file

@ -96,7 +96,9 @@ namespace gear {
}
enum
Capacity {SPINTIME ///< imminent activities
Capacity {DISPATCH ///< sent to work
,TENDNEXT ///< reserved for next task
,SPINTIME ///< awaiting imminent activities
,NEARTIME ///< capacity for active processing required
,WORKTIME ///< typical stable work task rhythm expected
,IDLETIME ///< time to go to sleep
@ -114,7 +116,18 @@ namespace gear {
{
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

@ -55,6 +55,7 @@
//#include "lib/util.hpp"
//#include <string>
#include <utility>
namespace vault{
@ -62,13 +63,14 @@ namespace gear {
// using util::isnil;
// using std::string;
using std::move;
namespace { // Scheduler default config
const auto IDLE_WAIT = 20ms; ///< sleep-recheck cycle for workers deemed _idle_
const size_t DISMISS_CYCLES = 100; ///< number of wait cycles before an idle worker terminates completely
Offset POLL_WAIT_DELAY{FSecs(1,1000)}; ///< delay until re-evaluating a condition previously found unsatisfied
}
namespace { // Scheduler default config
const auto IDLE_WAIT = 20ms; ///< sleep-recheck cycle for workers deemed _idle_
const size_t DISMISS_CYCLES = 100; ///< number of wait cycles before an idle worker terminates completely
Offset POLL_WAIT_DELAY{FSecs(1,1000)}; ///< delay until re-evaluating a condition previously found unsatisfied
}
@ -163,13 +165,11 @@ namespace gear {
/**
*
* The worker-Functor: called by the active Workers from the
* \ref WorkForce to pull / perform the actual render Activities.
*/
activity::Proc
getWork()
{
UNIMPLEMENTED("the Worker-Funkction");
}
activity::Proc getWork();
private:
void
@ -184,12 +184,37 @@ namespace gear {
* @return how to proceed further with this worker
*/
activity::Proc
scatteredDelay()
scatteredDelay (LoadController::Capacity capacity)
{
UNIMPLEMENTED("scattered short-term delay");
}
/**
* monad-like step sequence: perform sequence of steps,
* as long as the result remains activity::PASS
*/
struct WorkerInstruction
{
activity::Proc lastResult = activity::PASS;
/*** exposes the latest verdict as overall result */
operator activity::Proc()
{
return activity::SKIP == lastResult? activity::PASS
: lastResult;
}
template<class FUN>
WorkerInstruction
performStep (FUN step)
{
if (activity::PASS == lastResult)
lastResult = step();
return move(*this);
}
};
/** @internal expose a binding for Activity execution */
class ExecutionCtx;
};
@ -201,7 +226,7 @@ namespace gear {
* some aspects of Activity _activation_ however require external functionality,
* which for the purpose of language definition was abstracted as _Execution-context._
* The implementation of these binding functions fills in relevant external effects and
* is in fact supplied by the implementation internals of the scheduler itself.
* is in fact supplied by the implementation internals of the scheduler itself.
*/
class Scheduler::ExecutionCtx
: private Scheduler
@ -260,5 +285,39 @@ namespace gear {
/**
* @remarks this function is invoked from within the worker thread(s) and will
* - decide if and how the capacity of this worker shall be used right now
* - possibly go into a short targeted wait state to redirect capacity at a better time point
* - and most notably jump into the dispatch of the render Activities, to calculate media data.
* @return an instruction for the work::Worker how to proceed next:
* - activity::PROC causes the worker to poll again immediately
* - activity::SLEEP induces a sleep state
* - activity::HALT terminates the worker
*/
inline activity::Proc
Scheduler::getWork()
{
ExecutionCtx& ctx = ExecutionCtx::from(*this);
Time now = ctx.getSchedTime();
Time head = layer1_.headTime();
return WorkerInstruction{}
.performStep([&]{ return scatteredDelay(
loadControl_.incomingCapacity (head,now));
})
.performStep([&]{
Activity* act = layer2_.findWork(layer1_,now);
return layer2_.postDispatch (act, now, ctx, layer1_);
})
.performStep([&]{ return scatteredDelay(
loadControl_.outgoingCapacity (head,now));
})
;
}
}} // namespace vault::gear
#endif /*SRC_VAULT_GEAR_SCHEDULER_H_*/

View file

@ -436,7 +436,7 @@ namespace test {
*/
void
integratedWorkCycle()
{ // ===================================================================== setup a rigged Job
{ // ·==================================================================== setup a rigged Job
Time nominal{7,7};
Time start{0,1};
Time dead{0,10};
@ -455,7 +455,7 @@ namespace test {
detector.watchGate (anchor.next, "theGate");
// ===================================================================== setup test subject
// ·=================================================================== setup test subject
SchedulerInvocation queue;
SchedulerCommutator sched;
@ -477,7 +477,7 @@ namespace test {
});
// ===================================================================== actual test sequence
// ·=================================================================== actual test sequence
// Add the Activity-Term to be scheduled for planned start-Time
sched.postDispatch (&anchor, start, detector.executionCtx, queue);
CHECK (detector.ensureNoInvocation("testJob"));

View file

@ -81992,8 +81992,59 @@ 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="1697808055694" TEXT="mit der Work-Function abstimmen">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697808041495" ID="ID_492054934" MODIFIED="1698004006239" 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"/>
<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">
<icon BUILTIN="full-1"/>
</node>
<node CREATED="1698004032863" ID="ID_169532641" MODIFIED="1698009690679" TEXT="n&#xe4;chsten Task suchen">
<icon BUILTIN="full-2"/>
</node>
<node CREATED="1698004044189" ID="ID_1529366392" MODIFIED="1698009693216" TEXT="postDispatch">
<icon BUILTIN="full-3"/>
</node>
<node CREATED="1698004051651" ID="ID_1205197888" MODIFIED="1698009695809" TEXT="Kapazit&#xe4;t feststellen">
<icon BUILTIN="full-4"/>
</node>
</node>
<node CREATED="1698004064515" ID="ID_1757760062" MODIFIED="1698004067549" TEXT="R&#xfc;ckgabewert">
<node CREATED="1698004069585" ID="ID_1914419321" MODIFIED="1698004104844" TEXT="Reihenfolge der Quellen">
<node CREATED="1698004105859" ID="ID_755324904" MODIFIED="1698004117284" TEXT="incomingCapacity"/>
<node CREATED="1698004126047" ID="ID_1317095519" MODIFIED="1698004128011" TEXT="postDispatch">
<node CREATED="1698004165273" ID="ID_1299419336" MODIFIED="1698004170455" TEXT="ist entweder PASS"/>
<node CREATED="1698004170936" ID="ID_1553168494" MODIFIED="1698004185891" TEXT="oder SKIP transformiert &#x27fc; PASS"/>
<node CREATED="1698004189821" ID="ID_637853272" MODIFIED="1698004220843" TEXT="oder rekrusiver postDispatch">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
kann um f&#252;nf Ecken gehen; auch dispatchNotify landed irgend wann bei postDispatch
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1698004225008" ID="ID_460779820" MODIFIED="1698004240545" TEXT="&#x27f9; entweder PASS oder ernste Probleme"/>
</node>
<node CREATED="1698004128887" ID="ID_933518899" MODIFIED="1698004135501" TEXT="outgoingCapacity"/>
</node>
<node CREATED="1698006786524" ID="ID_1037494295" MODIFIED="1698009675035" TEXT="monadische Kontrollstruktur">
<icon BUILTIN="idea"/>
<node CREATED="1698006794562" ID="ID_1254874787" MODIFIED="1698006827275" TEXT="sonst verdeckt die Behandlung des Control-flow die Entscheidungs-Logik">
<icon BUILTIN="yes"/>
</node>
<node CREATED="1698006838477" ID="ID_247363146" MODIFIED="1698006845045" TEXT="Kapazit&#xe4;ts-Klassifikation"/>
<node CREATED="1698006846916" ID="ID_1307283652" MODIFIED="1698006863405" TEXT="Proze&#xdf;schritt-Ergebnis"/>
<node CREATED="1698006864065" ID="ID_1683660566" MODIFIED="1698006898512" TEXT="Junktor">
<node CREATED="1698006899389" ID="ID_886749855" MODIFIED="1698006904272" TEXT="Fortsetzen falls PROC"/>
<node CREATED="1698006905100" ID="ID_726868117" MODIFIED="1698006932612" TEXT="SKIP &#x27f6; Abbruch aber &#x27fc; PROC"/>
<node CREATED="1698006946326" ID="ID_165778182" MODIFIED="1698006960896" TEXT="WAIT &#x27f6; Abbruch und weitergeben"/>
</node>
</node>
</node>
<node CREATED="1698004014170" ID="ID_359097355" MODIFIED="1698004015766" TEXT="Test"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697808056565" ID="ID_10043675" MODIFIED="1697808062704" TEXT="Fehlerbehandlung bedenken">
<icon BUILTIN="flag-yellow"/>
@ -82138,16 +82189,13 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1697935685080" ID="ID_1125666331" MODIFIED="1697935700776" TEXT="Vorsicht: vorausschauend handeln"/>
<node CREATED="1697935701613" ID="ID_601914515" MODIFIED="1697935798105" TEXT="der Schlaf-Zyklus soll relativ lang sein">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
um das System nicht unn&#246;tig zu belasten
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1697935831136" ID="ID_328104821" MODIFIED="1697935849059" TEXT="polling workers stellen aber selbst eine Belastung dar">
<icon BUILTIN="messagebox_warning"/>
@ -82170,44 +82218,35 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1697935657451" ID="ID_1200603474" MODIFIED="1697935676437" TEXT="diese beenden sich dann nach einiger Zeit von selbst">
<node CREATED="1697936056094" ID="ID_1569058603" MODIFIED="1697936822180" TEXT="Scheduler mu&#xdf; daf&#xfc;r sorgen, da&#xdf; das auch m&#xf6;glich wird">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
Das bedeutet: bei nur vereinzelt vorhandenen Tasks d&#252;rfen diese nicht zuf&#228;llig verteilt werden (sonst bleiben alle Worker am Leben). Vielmehr mu&#223; bevorzugt derjenige den n&#228;chsten Task bekommen, der ohnehin<i>&#160; grade gearbeitet hat</i>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1697936111527" ID="ID_1844164309" MODIFIED="1697941569266" TEXT="&#x27f9; mu&#xdf; also einen &#xbb;Idler&#xab; anders behandeln als einen grade aktiven Worker">
<linktarget COLOR="#6463c4" DESTINATION="ID_1844164309" ENDARROW="Default" ENDINCLINATION="-359;14;" ID="Arrow_ID_1762094389" SOURCE="ID_387348315" STARTARROW="None" STARTINCLINATION="12;-45;"/>
<node CREATED="1697936891271" ID="ID_816798666" MODIFIED="1697939174942">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
Idler: findet <i>direkt beim Eintritt</i>&#160;in pullWork() nichts zu tun vor
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1697936959055" ID="ID_687912678" MODIFIED="1697939181596">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
Worker: findet <i>nach </i>einem Work-Zyklus nichts zu tun vor
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
</node>
@ -82234,30 +82273,24 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="help"/>
<node CREATED="1697937571163" ID="ID_1306343127" MODIFIED="1697937694750" TEXT="normalerweise nicht">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...weil der water-level ein internes Implementierungsdetail von Layer-1 ist, und der eigentliche Dispatch mit &quot;now&quot; erfolgt. M&#246;glicherweise hab' ich mich da verrant &#8212; andererseits wollte ich ganz explizit nicht &#252;berall und in jeder Activity auch noch eine Startzeit mitschleppen, sondern habe mich darauf verlegt, diese Information <i>kontextuell zu handhaben</i>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1697937696156" ID="ID_174871580" MODIFIED="1697937707679" TEXT="aber bei einem POST schon">
<node COLOR="#435e98" CREATED="1697937859072" ID="ID_598148359" MODIFIED="1697938012371" TEXT="redundante Startzeit-Info zahlt sich nun aus">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...und ich hatte k&#252;rzlich noch solche Zweifel ob das Design komplett entgleist, habe mich dann aber entschieden, locker zu lassen
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<linktarget COLOR="#5adeb2" DESTINATION="ID_598148359" ENDARROW="Default" ENDINCLINATION="52;-139;" ID="Arrow_ID_155448561" SOURCE="ID_496219214" STARTARROW="None" STARTINCLINATION="638;34;"/>
<icon BUILTIN="idea"/>
</node>
@ -82278,16 +82311,13 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="yes"/>
<node CREATED="1697942254924" ID="ID_112390329" MODIFIED="1697979569952" TEXT="Warte-Zyklen zuf&#xe4;llig verteilen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
damit im Schnitt jedes 1/Nte - Warte-Intervall sich ein Worker meldet
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<node CREATED="1697979636585" ID="ID_860834763" MODIFIED="1697979662307" TEXT="die Startpunkte der Idle-Zyklen auf die Idle-Periode verteilen"/>
<node CREATED="1697979662919" ID="ID_1977764043" MODIFIED="1697979714012" TEXT="aber analog auch warte-Pausen auf die zeitnah-Phase verteilen"/>
</node>
@ -82295,16 +82325,13 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1697942899578" ID="ID_1831185639" MODIFIED="1697942954171" TEXT="zeitnah-Phase sinnvoll bemessen">
<node CREATED="1697943207013" ID="ID_461693614" MODIFIED="1697943398859" TEXT="nur h&#xf6;chstens so lang wie man problemlos verschwenden kann">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
denn: innerhalb der zeitnah-Phase wird jeder verf&#252;gbare worker per gezieltem Schlaf auf die n&#228;chste headTime gesetzt, und damit ist er bis dahin geblockt. Also sollte es extrem unwahrscheinlich sein, da&#223; inzwischen so kurzfristig noch was dazwischen geplant wird
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1697943528922" ID="ID_1864150010" MODIFIED="1697943563874" TEXT="aber lang genug um kurzfristiges Polling, re-Scheduliing und Staffelungen abzudecken"/>
</node>
@ -82407,16 +82434,13 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="flag-yellow"/>
<node CREATED="1697983567535" ID="ID_567326127" MODIFIED="1697983640429" TEXT="ist eine Dispatch-Funktion">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
man schickt einen Worker in &#187;scattered delay&#171;
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="info"/>
<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"/>
@ -82426,6 +82450,13 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</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">
<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>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1697982436029" ID="ID_288711039" MODIFIED="1697982440270" TEXT="Test">
<icon BUILTIN="flag-yellow"/>
@ -89989,16 +90020,13 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="flag-yellow"/>
<node CREATED="1697981442202" ID="ID_1994085081" MODIFIED="1697981536989" TEXT="Ma&#xdf;gabe: statistische Auswertungen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
&#10233; bedeutet f&#252;r jedes Ereignis auch eine Kategorisierung zu erfassen, so da&#223; dann in der Auswertung sp&#228;ter proportionale Anteile beobachtbar werden
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<node CREATED="1697981581895" ID="ID_1199294273" MODIFIED="1697981641259" TEXT="wieviel Wartezeit verbringt ein aktiver Worker?"/>
<node CREATED="1697981666612" ID="ID_769519844" MODIFIED="1697981680252" TEXT="in welchen Phasen verbringt er diese Zeit?"/>
<node CREATED="1697981689097" ID="ID_16365365" MODIFIED="1697981718933" TEXT="was ist das &#x2205; Pr&#xfc;fintervall eines schlafenden Workers"/>