Scheduler: integrate sanity check on timings
...especially to prevent a deadline way too far into the future, since this would provoke the BlockFlow (epoch based) memory manager to run out of space. Just based on gut feeling, I am now imposing a limit of 20seconds, which, given current parametrisation, with a minimum spacing of 6.6ms and 500 Activities per Block would at maximum require 360 MiB for the Activities, or 3000 Blocks. With *that much* blocks, the linear search would degrade horribly anyway...
This commit is contained in:
parent
0ed7dba641
commit
892099412c
4 changed files with 101 additions and 21 deletions
|
|
@ -76,6 +76,7 @@
|
|||
#include "vault/gear/scheduler-invocation.hpp"
|
||||
#include "vault/gear/activity-lang.hpp"
|
||||
#include "lib/time/timevalue.hpp"
|
||||
#include "lib/format-string.hpp"
|
||||
#include "lib/nocopy.hpp"
|
||||
|
||||
#include <thread>
|
||||
|
|
@ -85,12 +86,19 @@
|
|||
namespace vault{
|
||||
namespace gear {
|
||||
|
||||
using lib::time::Offset;
|
||||
using lib::time::FSecs;
|
||||
using lib::time::Time;
|
||||
using std::atomic;
|
||||
using std::memory_order::memory_order_relaxed;
|
||||
using std::memory_order::memory_order_acquire;
|
||||
using std::memory_order::memory_order_release;
|
||||
|
||||
namespace { // Configuration / Scheduling limit
|
||||
|
||||
Offset FUTURE_PLANNING_LIMIT{FSecs{20}}; ///< limit timespan of deadline into the future (~360 MiB max)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************//**
|
||||
|
|
@ -156,6 +164,21 @@ namespace gear {
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
sanityCheck (ActivationEvent const& event, Time now)
|
||||
{
|
||||
if (event.startTime() == Time::ANYTIME)
|
||||
throw error::Fatal ("Attempt to schedule an Activity without valid start time");
|
||||
if (event.deathTime() == Time::NEVER)
|
||||
throw error::Fatal ("Attempt to schedule an Activity without valid deadline");
|
||||
Offset toDeadline{now, event.deathTime()};
|
||||
if (toDeadline > FUTURE_PLANNING_LIMIT)
|
||||
throw error::Fatal (util::_Fmt{"Attempt to schedule Activity %s "
|
||||
"with a deadline by %s into the future"}
|
||||
% *event.activity
|
||||
% toDeadline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decide if Activities shall be performed now and in this thread.
|
||||
* @param when the indicated time of start of the first Activity
|
||||
|
|
@ -224,6 +247,7 @@ namespace gear {
|
|||
if (!event) return activity::SKIP;
|
||||
|
||||
Time now = executionCtx.getSchedTime();
|
||||
sanityCheck (event, now);
|
||||
if (decideDispatchNow (event.startTime(), now))
|
||||
return ActivityLang::dispatchChain (event, executionCtx);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -112,14 +112,16 @@ namespace test {
|
|||
SchedulerInvocation queue;
|
||||
SchedulerCommutator sched;
|
||||
Activity activity;
|
||||
Time when{1,2};
|
||||
Time when{3,4};
|
||||
Time dead{5,6};
|
||||
|
||||
// use the ActivityDetector for test instrumentation...
|
||||
ActivityDetector detector;
|
||||
Time now = detector.executionCtx.getSchedTime();
|
||||
CHECK (now < dead);
|
||||
|
||||
// prepare scenario: some activity is enqueued
|
||||
queue.instruct ({activity, when});
|
||||
queue.instruct ({activity, when, dead});
|
||||
|
||||
sched.postDispatch (sched.findWork(queue,now), detector.executionCtx,queue);
|
||||
CHECK (detector.verifyInvocation("CTX-tick").arg(now));
|
||||
|
|
@ -438,7 +440,8 @@ namespace test {
|
|||
// rigged execution environment to detect activations--------------
|
||||
ActivityDetector detector;
|
||||
Activity& activity = detector.buildActivationProbe ("testActivity");
|
||||
|
||||
auto makeEvent = [&](Time start) { return ActivationEvent{activity, start, start+Time{0,1}}; };
|
||||
// set a dummy deadline to pass the sanity check
|
||||
SchedulerInvocation queue;
|
||||
SchedulerCommutator sched;
|
||||
|
||||
|
|
@ -456,14 +459,14 @@ namespace test {
|
|||
CHECK (not sched.holdsGroomingToken (myself));
|
||||
|
||||
// Activity immediately dispatched when on time and GroomingToken can be acquired
|
||||
CHECK (activity::PASS == sched.postDispatch (ActivationEvent{activity, past}, detector.executionCtx, queue));
|
||||
CHECK (activity::PASS == sched.postDispatch (makeEvent(past), detector.executionCtx, queue));
|
||||
CHECK (detector.verifyInvocation("testActivity").timeArg(now)); // was invoked immediately
|
||||
CHECK ( sched.holdsGroomingToken (myself));
|
||||
CHECK ( queue.empty());
|
||||
detector.incrementSeq(); // Seq-point-1 in the detector log
|
||||
|
||||
// future Activity is enqueued by short-circuit directly into the PriorityQueue if possible
|
||||
CHECK (activity::PASS == sched.postDispatch (ActivationEvent{activity, future}, detector.executionCtx, queue));
|
||||
CHECK (activity::PASS == sched.postDispatch (makeEvent(future), detector.executionCtx, queue));
|
||||
CHECK ( sched.holdsGroomingToken (myself));
|
||||
CHECK (not queue.empty());
|
||||
CHECK (isSameObject (activity, *queue.peekHead())); // appears at Head, implying it's in Priority-Queue
|
||||
|
|
@ -474,14 +477,14 @@ namespace test {
|
|||
CHECK (queue.empty());
|
||||
|
||||
// ...but GroomingToken is not acquired explicitly; Activity is just placed into the Instruct-Queue
|
||||
CHECK (activity::PASS == sched.postDispatch (ActivationEvent{activity, future}, detector.executionCtx, queue));
|
||||
CHECK (activity::PASS == sched.postDispatch (makeEvent(future), detector.executionCtx, queue));
|
||||
CHECK (not sched.holdsGroomingToken (myself));
|
||||
CHECK (not queue.peekHead()); // not appearing at Head this time,
|
||||
CHECK (not queue.empty()); // rather waiting in the Instruct-Queue
|
||||
|
||||
|
||||
blockGroomingToken(sched);
|
||||
CHECK (activity::PASS == sched.postDispatch (ActivationEvent{activity, now}, detector.executionCtx, queue));
|
||||
CHECK (activity::PASS == sched.postDispatch (makeEvent(now), detector.executionCtx, queue));
|
||||
CHECK (not sched.holdsGroomingToken (myself));
|
||||
CHECK (not queue.peekHead()); // was enqueued, not executed
|
||||
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ namespace test {
|
|||
void
|
||||
postNewTask (Scheduler& scheduler, Activity& chain, Time start)
|
||||
{
|
||||
ActivationEvent actEvent{chain, start};
|
||||
ActivationEvent actEvent{chain, start, start + Time{50,0}}; // add dummy deadline +50ms
|
||||
Scheduler::ExecutionCtx ctx{scheduler, actEvent};
|
||||
scheduler.layer2_.postDispatch (actEvent, ctx, scheduler.layer1_);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82080,21 +82080,74 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1697756908166" ID="ID_1142273023" MODIFIED="1699300683254" TEXT="Wrapper-Builder um den Activity-Term legen">
|
||||
<linktarget COLOR="#f4336b" DESTINATION="ID_1142273023" ENDARROW="Default" ENDINCLINATION="-737;663;" ID="Arrow_ID_891496003" SOURCE="ID_175313196" STARTARROW="None" STARTINCLINATION="1218;-76;"/>
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1698945250261" ID="ID_780386157" MODIFIED="1698946166942" TEXT="Zusatz-Angaben zur Relevanz">
|
||||
<node COLOR="#338800" CREATED="1698945250261" ID="ID_780386157" MODIFIED="1699376300350" TEXT="Zusatz-Angaben zur Relevanz">
|
||||
<linktarget COLOR="#3d3aa9" DESTINATION="ID_780386157" ENDARROW="Default" ENDINCLINATION="86;143;" ID="Arrow_ID_103420327" SOURCE="ID_1778628995" STARTARROW="None" STARTINCLINATION="317;25;"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#435e98" CREATED="1699376305031" ID="ID_65587622" MODIFIED="1699376321708" TEXT="ManifestationID"/>
|
||||
<node COLOR="#435e98" CREATED="1699376312965" ID="ID_730592934" MODIFIED="1699376321709" TEXT="isCompulsory"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1698947287399" ID="ID_391005911" LINK="#ID_1426746639" MODIFIED="1698947345862" TEXT="Job-Deadline auf API verpflichtend">
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1698947287399" FOLDED="true" ID="ID_391005911" LINK="#ID_1426746639" MODIFIED="1699376270521" TEXT="Job-Deadline auf API verpflichtend">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node COLOR="#5b280f" CREATED="1699310594544" ID="ID_1072047412" MODIFIED="1699310620293" TEXT="mit dem Builder-API nicht darstellbar">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1699310605911" ID="ID_169718532" MODIFIED="1699310630268" TEXT="kann nur eine Assertion einbauen">
|
||||
<icon BUILTIN="flag-pink"/>
|
||||
<node COLOR="#338800" CREATED="1699310605911" ID="ID_169718532" MODIFIED="1699372921757" TEXT="aber einen Check mit Exception kann man einbauen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Nicht am falschen Ende sparen hier! Das kostet nur ein paar Nanosekunden...
|
||||
(und ein paar Fixes in den Tests, damit die am sanityCheck vorbeikommen)
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1699373956162" ID="ID_1098257299" MODIFIED="1699376259965" TEXT="ebenso einen Check gegen Deadlines zu weit in der Zukunft">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1699373969470" ID="ID_396517654" MODIFIED="1699373978929" TEXT="sinnvoll dimensionieren?"/>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1699373980509" ID="ID_1475597715" MODIFIED="1699373990484" TEXT="man könnte hier auf den BlockFlow zugreifen">
|
||||
<icon BUILTIN="hourglass"/>
|
||||
</node>
|
||||
<node CREATED="1699373991478" ID="ID_167847312" MODIFIED="1699376244923" TEXT="erst mal fest verdrahten">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1699373997383" ID="ID_680337402" MODIFIED="1699374014940" TEXT="Block-Size: 500 ⟹ Frames pro Block"/>
|
||||
<node CREATED="1699374069953" ID="ID_987216063" MODIFIED="1699374077213" TEXT="initial Framerate: 5 * 25"/>
|
||||
<node CREATED="1699374241946" ID="ID_854095581" MODIFIED="1699374250957" TEXT="⟹ initial Epoch-Step 0.4sec"/>
|
||||
<node CREATED="1699374286828" ID="ID_1273383304" MODIFIED="1699374296403" TEXT="⟹ Limit bei 6666µs"/>
|
||||
<node CREATED="1699374536778" ID="ID_1215862863" MODIFIED="1699374571890" TEXT="sizeof(Activity) = 4*64byte = 256byte"/>
|
||||
<node CREATED="1699374595111" ID="ID_838506431" MODIFIED="1699374610445" TEXT="⟹ ein Block: 125KiB"/>
|
||||
<node CREATED="1699374690327" ID="ID_1827252278" MODIFIED="1699374702912" TEXT="bei kleinstem Spacing ⟹ max 3000 Blöcke"/>
|
||||
<node CREATED="1699374703645" ID="ID_870259225" MODIFIED="1699374725707">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
<b>20</b>sec ⟹ 366 MiB
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1699374714149" ID="ID_1607589409" MODIFIED="1699374716762" TEXT="das pack ma!"/>
|
||||
</node>
|
||||
<node CREATED="1699374728785" ID="ID_211476282" MODIFIED="1699376256811">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
also auf <b>20 Sekunden</b> in die Zukunft limitieren
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="forward"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1699245520392" ID="ID_1677467445" MODIFIED="1699310561557" TEXT="Builder-Funktionen">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1699373933315" ID="ID_501195368" MODIFIED="1699376262879" TEXT="eingebaut in Layer-2 .postDispatch()">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1699245520392" ID="ID_1677467445" MODIFIED="1699376290830" TEXT="Builder-Funktionen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1699245533215" ID="ID_1666620904" MODIFIED="1699310551449" TEXT="relative Zeitangabe">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
|
|
@ -82104,14 +82157,14 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<font ITALIC="true" NAME="SansSerif" SIZE="9"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1699245538409" ID="ID_1074993324" MODIFIED="1699246017064" TEXT="hier auch schon mal std::chrono mit integrieren (für Tests)">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1699245538409" ID="ID_1074993324" MODIFIED="1699376286627" TEXT="hier auch schon mal std::chrono mit integrieren (für Tests)">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1699245552636" ID="ID_1654937511" MODIFIED="1699246017063" TEXT="relative Deadline">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1699245552636" ID="ID_1654937511" MODIFIED="1699376287980" TEXT="relative Deadline">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1699245562635" ID="ID_1277275368" MODIFIED="1699246017063" TEXT="weitere Setter">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1699245562635" ID="ID_1277275368" MODIFIED="1699376289016" TEXT="weitere Setter">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1699245577969" ID="ID_1964298619" MODIFIED="1699310570096" TEXT="post() ausführen">
|
||||
|
|
|
|||
Loading…
Reference in a new issue