Job-Planning: implement braindead deadline calculation

...using hard coded values instead of observation of actual runtimes,
but at least the calculation scheme (now relocated from TimeAnchor to JobPlanning)
should be a reasonable starting point.

TODO: test fails...
This commit is contained in:
Fischlurch 2023-06-16 04:09:38 +02:00
parent 73a9e4495a
commit 6228c623b4
16 changed files with 311 additions and 89 deletions

View file

@ -38,10 +38,10 @@
#include "steam/common.hpp"
#include "steam/mobject/model-port.hpp"
#include "steam/engine/time-anchor.hpp"
#include "steam/engine/frame-coord.hpp"
#include "steam/engine/job-ticket.hpp"
#include "steam/engine/job-planning.hpp"
#include "steam/play/timings.hpp"
#include "steam/play/output-slot.hpp"
#include "lib/iter-tree-explorer.hpp"
#include "lib/time/timevalue.hpp"

View file

@ -34,11 +34,14 @@
#include "lib/nocopy.hpp"
#include "lib/hash-value.h"
#include "lib/iter-adapter-stl.hpp"
#include "lib/time/timevalue.hpp"
#include "vault/engine/job.h" //////////////////////////////////////////////////////////////////TICKET #1295 : rather need a way to retrieve a real JobFunctor building block from the ProcNode
#include <deque>
using lib::HashVal;
using lib::time::FSecs; ////TODO using hard wired value
using lib::time::Duration;
namespace steam {
@ -117,6 +120,13 @@ namespace engine {
REQUIRE (action_);
return *action_; ///////////////////////////////////////////////////////////////////////TICKET #1295 : decision on actual JobFunctor and invocation parameters
}
Duration
getUpperBoundRuntime() const
{
///////////////////////////////////////////////////////////////////////////TICKET #1283 : lay foundation how to observe timing behaviour for a render pipeline
return Duration{FSecs{1,50}}; // Uh-Oh booo
}
};

View file

@ -50,6 +50,7 @@
#include "steam/engine/job-ticket.hpp"
#include "steam/engine/frame-coord.hpp"
#include "steam/play/output-slot.hpp"
#include "steam/play/timings.hpp"
#include "lib/time/timevalue.hpp"
//#include "lib/iter-explorer.hpp"
//#include "lib/iter-adapter.hpp"
@ -63,7 +64,10 @@ namespace engine {
namespace error = lumiera::error;
using play::DataSink;
using lib::time::TimeValue;
using play::Timings;
using lib::time::Time;
using lib::time::Duration;
using lib::time::TimeValue; ////////TODO for FrameLocator, could be obsolete
using util::unConst;
using util::isnil;
@ -97,16 +101,6 @@ namespace engine {
, outputSink_{sink}
{ }
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 :: to be refactored...
/** further job planning can be initiated by continuing off a given previous planning state.
* This is how the forks are created, expanding into a multitude of prerequisites for
* the job in question.
*/
JobPlanning (JobTicket::ExplorationState const& startingPoint, FrameCoord requestedFrame)
: plannedOperations_(startingPoint)
, point_to_calculate_(requestedFrame)
{ }
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 :: to be refactored...
// using the standard copy operations
@ -123,6 +117,52 @@ namespace engine {
return job;
}
/**
* Calculate the latest time point when to _start_ the job,
* so it can still possibly reach the timing goal.
* @return time point in wall-clock-time, or Time::ANYTIME if unconstrained
*/
Time
determineDeadline(Timings const& timings)
{
switch (timings.playbackUrgency)
{
case play::ASAP:
case play::NICE:
return Time::ANYTIME;
case play::TIMEBOUND:
return timings.getTimeDue(frameCoord_.absoluteFrameNumber)
- totalLatency(timings);
}
NOTREACHED ("unexpected playbackUrgency");
}
/**
* Determine a timing buffer for flexibility to allow starting the job
* already before its deadline; especially for real-time playback this leeway
* is rather limited, and constrained by the earliest time the target buffer
* is already allotted and ready to receive data.
* @return tolerance duration
* - Duration::NIL if deadline has to be matched with maximum precision
* - Duration::MAX for unlimited leeway to start anytime before the deadline
*/
Duration
determineLeeway(Timings const&)
{
UNIMPLEMENTED ("Job planning logic to establish Leeway for scheduling");
}
private:
Duration
totalLatency (Timings const& timings)
{
return jobTicket_.getExpectedRuntime()
+ timings.currentEngineLatency()
+ timings.outputLatency;
}
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 :: to be refactored...
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : likely to become obsolete
@ -288,13 +328,13 @@ namespace engine {
return accessJobTicket (location.modelPortIDX, location.absoluteNominalTime);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : likely to become obsolete
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : likely to become obsolete
bool canContinue (FrameCoord const& location)
{
// return not isEndOfChunk (location.absoluteFrameNumber,
// location.modelPort);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : likely to become obsolete
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : likely to become obsolete
protected:
virtual JobTicket& accessJobTicket (size_t, TimeValue nominalTime) =0;

View file

@ -39,14 +39,20 @@
namespace steam {
namespace engine {
namespace { // Details...
lib::Depend<vault::engine::NopJobFunctor> nopFunctor;
} // (END) Details...
using vault::engine::JobClosure;
using lib::HashVal;
using lib::unConst;
using lib::time::FSecs;
namespace { // Details...
lib::Depend<vault::engine::NopJobFunctor> nopFunctor;
/* ======== hard wired =================*/
const FSecs JOB_MINIMUM_RUNTIME{1,1000};
} // (END) Details...
@ -69,7 +75,7 @@ namespace engine {
* after the last Builder run created this part of the render network.
*/
Job
JobTicket::createJobFor (FrameCoord coordinates) const
JobTicket::createJobFor (FrameCoord coordinates)
{
Time nominalTime = coordinates.absoluteNominalTime;
if (this->empty())
@ -86,6 +92,25 @@ namespace engine {
}
}
/**
* Use observed runtime values of past job invocations to guess a sensible bound
* for the calculation time to expect for next invocation.
* @todo 6/2023 placeholder implementation with hard wired values in ExitNode
*/
Duration
JobTicket::getExpectedRuntime()
{
if (this->empty())
return Duration{JOB_MINIMUM_RUNTIME};
else
{
REQUIRE (isValid(), "Attempt to determine timings for incomplete or unspecified render plan.");
return provision_.exitNode.getUpperBoundRuntime();
}
}
/**
* Tag the precomputed invocation ID with the nominal frame time
*/

View file

@ -39,7 +39,7 @@
#include "vault/engine/job.h"
#include "steam/engine/frame-coord.hpp"
#include "steam/engine/exit-node.hpp"
#include "lib/hierarchy-orientation-indicator.hpp"
#include "lib/time/timevalue.hpp"
#include "lib/linked-elements.hpp"
#include "lib/util-foreach.hpp"
#include "lib/iter-adapter.hpp"
@ -56,8 +56,8 @@ namespace engine {
using vault::engine::Job;
using vault::engine::JobFunctor;
using vault::engine::JobClosure; /////////////////////////////////////////////////////////////////////TICKET #1287 : fix actual interface down to JobFunctor (after removing C structs)
using lib::time::Duration;
using lib::LinkedElements;
using lib::OrientationIndicator;
using util::isnil;
using lib::HashVal;
using lib::LUID;
@ -142,7 +142,9 @@ using lib::LUID;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 : likely to become obsolete
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 :: to be refactored...
Job createJobFor (FrameCoord coordinates) const;
Job createJobFor (FrameCoord coordinates);
Duration getExpectedRuntime();
auto
getPrerequisites ()

View file

@ -105,29 +105,6 @@ namespace engine {
FrameCnt anchorPoint_;
Time relatedRealTime_;
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1301
////////////////////////////////////////////////////////////////////////////////////////////////OOO sensible calculation, but pointless in TimeAnchor
static Time
expectedTimeofArival (play::Timings const& timings, FrameCnt startFrame, Offset startDelay)
{
Duration totalLatency = startDelay
+ timings.currentEngineLatency()
+ timings.outputLatency;
TimeVar deadline;
switch (timings.playbackUrgency)
{
case play::ASAP:
case play::NICE:
deadline = RealClock::now() + totalLatency;
break;
case play::TIMEBOUND:
deadline = timings.getTimeDue(startFrame) - totalLatency;
break;
}
return deadline;
}
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1301
static Time
expectedTimeofArival (play::Timings const& timings, FrameCnt startFrame, Offset startDelay)
{

View file

@ -70,15 +70,25 @@ namespace play {
* and the latency/speed requirements of the output.
*/
Timings::Timings (FrameRate fps)
: grid_(buildStandardGridForFramerate(fps))
, playbackUrgency (ASAP)
, playbackSpeed (1)
, scheduledDelivery(Time::NEVER)
, outputLatency (Duration::NIL)
: grid_{buildStandardGridForFramerate(fps)}
, playbackUrgency {ASAP}
, playbackSpeed {1}
, scheduledDelivery{Time::NEVER}
, outputLatency {Duration::NIL}
{
ENSURE (grid_);
}
Timings::Timings (FrameRate fps, Time realTimeAnchor)
: grid_{buildStandardGridForFramerate(fps)}
, playbackUrgency {TIMEBOUND}
, playbackSpeed {1}
, scheduledDelivery{realTimeAnchor}
, outputLatency {Duration::NIL}
{
ENSURE (grid_);
}
//////////////////////////////////////////////////////////////////TODO ctors for use in the real player/engine?

View file

@ -105,6 +105,8 @@ namespace play {
explicit
Timings (FrameRate fps);
Timings (FrameRate fps, Time realTimeAnchor);
// default copy acceptable

View file

@ -28,13 +28,13 @@
#include "vault/engine/engine-config.hpp"
#include "lib/time/timevalue.hpp"
#include <boost/rational.hpp>
#include "lib/rational.hpp"
using boost::rational;
using lib::time::FrameRate;
using lib::time::FSecs;
using util::Rat;
namespace vault{
@ -42,8 +42,7 @@ namespace engine {
namespace { // Hard wired placeholder settings...
const rational<uint> ONE_THIRD(1,3);
const rational<uint> EIGHTY_PERCENT(8,10);
const auto EIGHTY_PERCENT = 8_r/10;
const Duration DEFAULT_ENGINE_LATENCY = EIGHTY_PERCENT * Duration(1, FrameRate{25}); ///////TODO: shouldn't be hard wired and shouldn't be calculated in static/global init
const Duration DEFAULT_JOB_PLANNING_TURNOVER(FSecs(3,2));

View file

@ -34,6 +34,7 @@
#include "steam/play/dummy-play-connection.hpp"
#include "steam/mobject/model-port.hpp"
#include "steam/engine/dispatcher.hpp"
#include "steam/engine/time-anchor.hpp"
#include "steam/play/timings.hpp"
#include "lib/time/timevalue.hpp"
//#include "lib/time/timequant.hpp"

View file

@ -205,7 +205,7 @@ namespace test {
CHECK (not isnil (pipeline));
CHECK (nullptr == pipeline->first); // is a top-level ticket
JobTicket const& ticket = *pipeline->second;
JobTicket& ticket = *pipeline->second;
FrameCoord dummy{Time::ZERO}; // actual time point is irrelevant here
Job job = ticket.createJobFor(dummy);

View file

@ -37,7 +37,7 @@
#include "steam/play/timings.hpp"
#include "lib/time/timevalue.hpp"
//#include "lib/time/timequant.hpp"
//#include "lib/format-cout.hpp"
#include "lib/format-cout.hpp" ///////////////TODO
//#include "lib/depend.hpp"
//#include "lib/itertools.hpp"
//#include "lib/util-coll.hpp"
@ -131,6 +131,24 @@ namespace test {
void
calculateDeadline()
{
MockDispatcher dispatcher;
play::Timings timings (FrameRate::PAL, Time{0,0,5});
auto [port,sink] = dispatcher.getDummyConnection(1);
Time nominalTime{200,0};
size_t portIDX = dispatcher.resolveModelPort (port);
FrameCoord frame{nominalTime, portIDX};
JobTicket& ticket = dispatcher.getJobTicketFor(frame);
JobPlanning plan{frame,ticket,sink};
timings.playbackUrgency = play::ASAP;
cout << plan.determineDeadline(timings) <<endl;
CHECK (Time::ANYTIME == plan.determineDeadline (timings));
timings.playbackUrgency = play::TIMEBOUND;
////////TODO where to set the anchor point realTime <-> nominalTime ??
cout << plan.determineDeadline(timings) <<endl;
}
@ -141,6 +159,7 @@ namespace test {
void
setupDependentJob()
{
UNIMPLEMENTED ("chained deadlines");
}
};

View file

@ -85,6 +85,7 @@ namespace test {
using util::isnil;
using util::isSameObject;
using fixture::Segmentation;
using vault::RealClock;
using vault::engine::Job;
using vault::engine::JobClosure;

View file

@ -86,7 +86,7 @@ namespace test {
CHECK (3 == mockSegs.size());
fixture::Segment const& seg = mockSegs[Time{0,15}]; // access anywhere 10s <= t < 20s
JobTicket const& ticket = seg.jobTicket(0);
JobTicket& ticket = seg.jobTicket(0);
FrameCoord coord{Time(0,15)};
Job job = ticket.createJobFor(coord);
@ -174,7 +174,7 @@ namespace test {
CHECK (1 == mockSegs.size());
CHECK (Time::MIN == mockSegs[someTime].start());
CHECK (Time::MAX == mockSegs[someTime].after());
JobTicket const& ticket = mockSegs[someTime].jobTicket(0);
JobTicket& ticket = mockSegs[someTime].jobTicket(0);
CHECK (not util::isSameObject (ticket, JobTicket::NOP));
Job someJob = ticket.createJobFor(coord); // JobTicket uses, but does not check the time given in FrameCoord
@ -328,7 +328,7 @@ namespace test {
auto prereq = ticket.getPrerequisites();
CHECK (not isnil (prereq));
JobTicket const& preTicket = *prereq;
JobTicket& preTicket = *prereq;
++prereq;
CHECK (isnil (prereq));
@ -367,7 +367,7 @@ namespace test {
return ticket.getPrerequisites();
})
.expandAll()
.transform ([&](JobTicket const& ticket)
.transform ([&](JobTicket& ticket)
{
return ticket.createJobFor(coord).parameter.invoKey.part.a;
});

View file

@ -108,7 +108,7 @@ namespace test {
Segment const& seg = segmentation[Time::ANYTIME]; // thus accessed time point is irrelevant
// verify mapped JobTicket is assembled according to above spec...
auto getMarker = [](JobTicket const& ticket)
auto getMarker = [](JobTicket& ticket)
{
engine::FrameCoord dummyFrame;
Job job = ticket.createJobFor(dummyFrame);

View file

@ -69098,34 +69098,23 @@
</html></richcontent>
<icon BUILTIN="idea"/>
</node>
<node CREATED="1681167308878" ID="ID_43374924" MODIFIED="1681167532633" TEXT="Entwicklungs-Stand">
<icon BUILTIN="info"/>
<node COLOR="#435e98" CREATED="1681167354768" ID="ID_728804120" MODIFIED="1681167483523" TEXT="seit 2012">
<icon BUILTIN="forward"/>
<node CREATED="1681167362351" ID="ID_1740546811" MODIFIED="1681167371954" TEXT="Konzept und Struktur definiert"/>
<node CREATED="1681167383228" ID="ID_1536175314" MODIFIED="1681167401168" TEXT="noch g&#xe4;nzlich unklar wie die Auswertung / Job-Konstruktion funktionieren soll"/>
<node CREATED="1681167406089" ID="ID_1405586078" MODIFIED="1681167443145" TEXT="begr&#xfc;ndet durch die ebenfalls seinerzeit nur skizzierte Arbeitsweise der ProcNode"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1681167868332" ID="ID_1179827139" MODIFIED="1681167938418">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
<u>unklar</u>: <font face="Monospaced" color="#43226f">JobTicket::startExploration()</font>&#160;&#8212; wie wird die eigentliche Planung eingef&#228;delt?
</p>
</body>
</html></richcontent>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1686873541317" ID="ID_1804172635" MODIFIED="1686873628786" TEXT="eng mit dem Monaden-basierten Auswertungsmechanismus verwoben">
<icon BUILTIN="messagebox_warning"/>
</node>
<node COLOR="#5b280f" CREATED="1686873563463" ID="ID_1311610646" MODIFIED="1686873630966" TEXT="enth&#xe4;lt Differenzierung f&#xfc;r mehrere Channels">
<icon BUILTIN="button_cancel"/>
<node COLOR="#338800" CREATED="1686873634808" ID="ID_44461929" MODIFIED="1686873638856" TEXT="zur&#xfc;ckgebaut">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1681167470153" ID="ID_1806361283" MODIFIED="1681167480840" TEXT="PlaybackVerticalSlice">
<icon BUILTIN="hourglass"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1681839381459" ID="ID_697548050" MODIFIED="1686841566662" TEXT="im ersten Schritt: mit der neuen Struktur ohne Monaden nutzbar machen">
<arrowlink COLOR="#fe80b2" DESTINATION="ID_310889374" ENDARROW="Default" ENDINCLINATION="-503;-32;" ID="Arrow_ID_1927639949" STARTARROW="None" STARTINCLINATION="230;9;"/>
</node>
<node COLOR="#338800" CREATED="1686873575574" ID="ID_1754560865" MODIFIED="1686873615335" TEXT="Umbau: mit neuer Struktur ohne Monaden nutzbar machen">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1686873596600" ID="ID_1924946981" MODIFIED="1686873656415" TEXT="Umbau: nun unter / hinter das JobPlanning legen">
<icon BUILTIN="pencil"/>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1686873681722" ID="ID_574294902" MODIFIED="1686873692546" TEXT="in neuen Dispatcher + RenderDrive integriert">
<icon BUILTIN="hourglass"/>
</node>
</node>
<node CREATED="1512925246057" ID="ID_181262071" MODIFIED="1686839807822" TEXT="JobPlanning">
@ -69986,7 +69975,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</body>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685403325222" ID="ID_2694625" MODIFIED="1685403350256" TEXT="jedwede Latenz-Kompensation / Deadline-Bestimmung in die Planning-Pipeline verschieben">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685403325222" ID="ID_2694625" LINK="#ID_109124269" MODIFIED="1685403350256" TEXT="jedwede Latenz-Kompensation / Deadline-Bestimmung in die Planning-Pipeline verschieben">
<icon BUILTIN="flag-yellow"/>
</node>
<node CREATED="1685406566342" ID="ID_524698195" MODIFIED="1685406623527" TEXT="dann bleibt aber nix mehr &#xfc;brig....???">
@ -70024,6 +70013,19 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</body>
</html></richcontent>
<icon BUILTIN="help"/>
<node CREATED="1686878263958" ID="ID_1822381853" MODIFIED="1686878292683" TEXT="jetzt brauch ich die Frame-Nr doch noch!">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
f&#252;r die Deadline-Berechnung...
</p>
</body>
</html></richcontent>
<icon BUILTIN="stop-sign"/>
</node>
</node>
</node>
<node CREATED="1681169265752" ID="ID_388188594" MODIFIED="1681169268100" TEXT="JobTicket">
@ -75722,6 +75724,48 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686793444999" ID="ID_890638508" MODIFIED="1686793453060" TEXT="einfacher Job">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686873856076" ID="ID_1099231430" MODIFIED="1686874375053" TEXT="eigentlich liegt das Wissen dar&#xfc;ber im JobFunktor">
<arrowlink COLOR="#a56c6d" DESTINATION="ID_1464401657" ENDARROW="Default" ENDINCLINATION="-74;-579;" ID="Arrow_ID_1368232066" STARTARROW="None" STARTINCLINATION="933;50;"/>
<icon BUILTIN="idea"/>
<node COLOR="#338800" CREATED="1686874175948" HGAP="50" ID="ID_525505445" MODIFIED="1686878346429" TEXT="vorl&#xe4;ufige Fake-Info vorsehen" VSHIFT="-3">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1686874325457" ID="ID_1367759543" MODIFIED="1686878348271" TEXT="in ExitNode">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686874330784" ID="ID_1065139085" MODIFIED="1686874366808" TEXT="und dort per Test-Spec aus dem Mock injizieren">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686874081293" ID="ID_1358950308" MODIFIED="1686874160334" TEXT="Zugriff sollte aber &#xfc;ber das JobTIcket-API gef&#xfc;hrt werden">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
und zwar wegen <i>Separation of Concerns</i>&#160;&#160;&#160;&#8212;&#160;&#160;der JobFunctor ist kein Informations-Service (genau daf&#252;r haben wir ja das JobTicket geschaffen)
</p>
</body>
</html></richcontent>
<icon BUILTIN="yes"/>
</node>
<node COLOR="#338800" CREATED="1686874427511" ID="ID_109124269" MODIFIED="1686878357594" TEXT="die bisher in TimeAnchor gecodete Logik hierher verschieben">
<icon BUILTIN="flag-yellow"/>
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686875298675" ID="ID_981450024" MODIFIED="1686875356324" TEXT="Logik der Berechnung ausarbeiten">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1686878372095" ID="ID_735392622" MODIFIED="1686878381499" TEXT="Gesamt-Latenz">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1686878360841" ID="ID_26327492" MODIFIED="1686879600114" TEXT="f&#xfc;r Deadline eigentlich nur bei TIMEBOUND">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1686879601311" ID="ID_1446511354" MODIFIED="1686879625110" TEXT="Frage: wo wird nun der Anker zur wall-clock-Time etabliert?">
<icon BUILTIN="help"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686793449011" ID="ID_1790599874" MODIFIED="1686793453060" TEXT="abh&#xe4;ngiger Job">
<icon BUILTIN="flag-yellow"/>
@ -75782,6 +75826,43 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686873234880" ID="ID_1662721717" MODIFIED="1686873239870" TEXT="determineDeadline">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1686874949274" ID="ID_355623699" MODIFIED="1686875277005">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
<b>Definition</b>: der letzte Zeitpunkt an dem der Job starten darf
</p>
</body>
</html></richcontent>
<icon BUILTIN="info"/>
</node>
<node CREATED="1686876114974" ID="ID_914514510" MODIFIED="1686876118761" TEXT="Argument: Timings"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686878317271" ID="ID_1008817240" MODIFIED="1686878338708" TEXT="auch die FrameNr nun stets in den FrameCoord notwendig">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686875085793" ID="ID_922531661" MODIFIED="1686875092431" TEXT="determineLeeway">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1686874949274" ID="ID_1842763016" MODIFIED="1686875271688">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
<b>Definition</b>: Pufferzeit, um die der Job bereits fr&#252;her starten kann
</p>
</body>
</html></richcontent>
<icon BUILTIN="info"/>
</node>
<node CREATED="1686876114974" ID="ID_1618175383" MODIFIED="1686876118761" TEXT="Argument: Timings"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685802570984" ID="ID_1417369009" MODIFIED="1685802579931" TEXT="Daten-Anordnung f&#xfc;r Jobs vorbereiten">
@ -75840,11 +75921,22 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686793470108" HGAP="-9" ID="ID_1024827381" MODIFIED="1686793480495" TEXT="JobPlanning_test" VSHIFT="7">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686793496442" ID="ID_1934790434" MODIFIED="1686793516470" TEXT="simpleUsage">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1686793496442" ID="ID_1934790434" MODIFIED="1686873178829" TEXT="simpleUsage">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686793496443" ID="ID_1476053415" MODIFIED="1686793514422" TEXT="calculateDeadline">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1686880606987" ID="ID_1127724242" MODIFIED="1686880645005" TEXT="TIMEBOUND - Berechnung wohl nicht korrekt">
<icon BUILTIN="broken-line"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1686880632623" ID="ID_1121171298" MODIFIED="1686880760729" TEXT="Deadline = 0:04:59.908"/>
<node CREATED="1686880647956" ID="ID_1076439422" MODIFIED="1686880753302" TEXT="w&#xfc;rde erwarten">
<icon BUILTIN="info"/>
<node CREATED="1686880655108" ID="ID_1642227624" MODIFIED="1686880681337" TEXT="EngineLatency = 80% der Frame-Dur &#x2259; 32ms"/>
<node CREATED="1686880685685" ID="ID_1840636821" MODIFIED="1686880697546" TEXT="Job-Zeit habe ich hart gecodet auf 20ms"/>
<node CREATED="1686880702989" ID="ID_462263183" MODIFIED="1686880715360" TEXT="nominalTime = 200ms"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1686880716476" ID="ID_1325275413" MODIFIED="1686880748644" TEXT="&#xd83e;&#xdc32; 5h +200ms - 52ms"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686793496443" ID="ID_1152978912" MODIFIED="1686793511894" TEXT="setupDependentJob">
<icon BUILTIN="flag-yellow"/>
@ -75932,7 +76024,47 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1512925253328" ID="ID_922277724" MODIFIED="1686620124221" TEXT="JobTicket">
<linktarget COLOR="#82597c" DESTINATION="ID_922277724" ENDARROW="Default" ENDINCLINATION="43;-81;" ID="Arrow_ID_941233317" SOURCE="ID_946385163" STARTARROW="None" STARTINCLINATION="-124;34;"/>
<icon BUILTIN="prepare"/>
<node CREATED="1681166276225" ID="ID_877524227" MODIFIED="1681166317636" TEXT="ein Execution-Plan g&#xfc;litg f&#xfc;r ein Segment + ModelPort"/>
<node CREATED="1681166276225" HGAP="5" ID="ID_877524227" MODIFIED="1686873733037" TEXT="ein Execution-Plan g&#xfc;litg f&#xfc;r ein Segment + ModelPort" VSHIFT="-7">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1681167308878" HGAP="34" ID="ID_43374924" MODIFIED="1686873721547" TEXT="Entwicklungs-Stand" VSHIFT="-2">
<icon BUILTIN="info"/>
<node COLOR="#435e98" CREATED="1681167354768" ID="ID_728804120" MODIFIED="1681167483523" TEXT="seit 2012">
<icon BUILTIN="forward"/>
<node CREATED="1681167362351" ID="ID_1740546811" MODIFIED="1681167371954" TEXT="Konzept und Struktur definiert"/>
<node CREATED="1681167383228" ID="ID_1536175314" MODIFIED="1681167401168" TEXT="noch g&#xe4;nzlich unklar wie die Auswertung / Job-Konstruktion funktionieren soll"/>
<node CREATED="1681167406089" ID="ID_1405586078" MODIFIED="1681167443145" TEXT="begr&#xfc;ndet durch die ebenfalls seinerzeit nur skizzierte Arbeitsweise der ProcNode"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1681167868332" ID="ID_1179827139" MODIFIED="1681167938418">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
<u>unklar</u>: <font face="Monospaced" color="#43226f">JobTicket::startExploration()</font>&#160;&#8212; wie wird die eigentliche Planung eingef&#228;delt?
</p>
</body>
</html></richcontent>
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1681167470153" ID="ID_1806361283" MODIFIED="1686873362861" TEXT="PlaybackVerticalSlice">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1681839381459" ID="ID_697548050" MODIFIED="1686873358538" TEXT="im ersten Schritt: mit der neuen Struktur ohne Monaden nutzbar machen">
<arrowlink COLOR="#fe80b2" DESTINATION="ID_310889374" ENDARROW="Default" ENDINCLINATION="-503;-32;" ID="Arrow_ID_1927639949" STARTARROW="None" STARTINCLINATION="230;9;"/>
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1686873778318" ID="ID_1659931389" MODIFIED="1686873796563" TEXT="das ganze Konzept &#xbb;ExplorationState&#xab; komplett durch eine Iterator-Pipeline abgel&#xf6;st">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686873367196" ID="ID_194165702" MODIFIED="1686873380336" TEXT="Bedeutung der dahinter stehenden ExitNode herausarbeiten">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1686873389042" ID="ID_1200787712" MODIFIED="1686873402712" TEXT="dahinter stehende JobFunctor + Parameter kl&#xe4;ren">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
<node CREATED="1681167533752" ID="ID_1794156121" MODIFIED="1681167538096" TEXT="Anforderungen">
<node COLOR="#5b280f" CREATED="1681167546919" ID="ID_1656777068" MODIFIED="1683836193612" TEXT="startExploration()">
<icon BUILTIN="button_cancel"/>
@ -76732,6 +76864,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685033995127" ID="ID_1464401657" MODIFIED="1685034032376" TEXT="kann seine Startzeit dynamisch sch&#xe4;tzen">
<linktarget COLOR="#a56c6d" DESTINATION="ID_1464401657" ENDARROW="Default" ENDINCLINATION="-74;-579;" ID="Arrow_ID_1368232066" SOURCE="ID_1099231430" STARTARROW="None" STARTINCLINATION="933;50;"/>
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685034033363" ID="ID_1119701449" MODIFIED="1685034041276" TEXT="zu gegebener Deadline">
<icon BUILTIN="flag-yellow"/>
@ -76745,6 +76878,9 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1686874287112" ID="ID_637268181" MODIFIED="1686874300648" TEXT="Zusammenarbeit mit ExitNode noch unklar">
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
</node>
</node>