Scheduler-test: calculate linear model as test result

Use the statistic functions imported recently from Yoshimi-test
to compute a linear regression model as immediate test result.

Combining several measurement series, this allows to draw conclusions
about some generic traits and limitations of the scheduler.
This commit is contained in:
Fischlurch 2024-04-09 01:51:03 +02:00
parent 3517ab6965
commit 6e7f9edf43
5 changed files with 138 additions and 38 deletions

View file

@ -245,6 +245,12 @@ namespace stat{
double x;
double y;
double w;
RegressionPoint (double vx, double vy, double vw=1.0)
: x{vx}
, y{vy}
, w{vw}
{ }
};
using RegressionData = std::vector<RegressionPoint>;

View file

@ -390,16 +390,39 @@ namespace test {
cpuLoad.calibrate();
//////////////////////////////////////////////////////////////////TODO for development only
MARK_TEST_FUN
// TestChainLoad testLoad{64};
// testLoad.configure_isolated_nodes()
// .buildTopology()
TestChainLoad testLoad{50};
testLoad.configure_isolated_nodes()
.buildTopology()
// .printTopologyDOT()
// .printTopologyStatistics();
.printTopologyStatistics();
{
TRANSIENTLY(work::Config::COMPUTATION_CAPACITY) = 4;
BlockFlowAlloc bFlow;
EngineObserver watch;
Scheduler scheduler{bFlow, watch};
auto set1 = testLoad.setupSchedule(scheduler)
.withLevelDuration(200us)
.withJobDeadline(100ms)
.withUpfrontPlanning()
.withLoadTimeBase(2ms)
.withInstrumentation();
double runTime = set1.launch_and_wait();
auto stat = set1.getInvocationStatistic();
cout << "time="<<runTime/1000
<< " covered="<<stat.coveredTime / 1000
<< " avgconc="<<stat.avgConcurrency
<<endl;
}
return;
struct Setup
: StressRig, bench::LoadPeak_ParamRange_Evaluation
{
uint CONCURRENCY = 4;
uint REPETITIONS = 40;
auto testLoad(Param nodes)
{
@ -410,15 +433,20 @@ namespace test {
auto testSetup (TestLoad& testLoad)
{
return StressRig::testSetup(testLoad)
.withLoadTimeBase(500us);
.withLoadTimeBase(2ms);
}
};
auto results = StressRig::with<Setup>()
.perform<bench::ParameterRange> (2,64);
.perform<bench::ParameterRange> (10,100);
cout << "───═══───═══───═══───═══───═══───═══───═══───═══───═══───═══───"<<endl;
cout << Setup::renderGnuplot (results);
cout << "───═══───═══───═══───═══───═══───═══───═══───═══───═══───═══───"<<endl;
auto [socket,gradient,v1,v2,corr,maxDelta,stdev] = bench::linearRegression (results.param, results.time);
cout << _Fmt{"Model: %3.2f·p + %3.2f corr=%4.2f Δmax=%4.2f σ=%4.2f"}
% gradient % socket % corr % maxDelta % stdev
<< endl;
}

View file

@ -151,6 +151,7 @@
#include "lib/format-string.hpp"
#include "lib/format-cout.hpp"
#include "lib/gnuplot-gen.hpp"
#include "lib/stat/statistic.hpp"
#include "lib/stat/data.hpp"
#include "lib/util.hpp"
@ -529,6 +530,22 @@ namespace test {
using lib::stat::CSVData;
using IncidenceStat = lib::IncidenceCount::Statistic;
/**
* Calculate a linear regression model for two table columns
* @return a tuple `(socket,gradient,Vector(predicted),Vector(deltas),correlation,maxDelta,stdev)`
*/
template<typename F, typename G>
auto
linearRegression (Column<F> const& x, Column<G> const& y)
{
lib::stat::RegressionData points;
size_t cnt = min (x.data.size(), y.data.size());
points.reserve (cnt);
for (size_t i=0; i < cnt; ++i)
points.emplace_back (x.data[i], y.data[i]);
return lib::stat::computeLinearRegression (points);
}
/**
* Mix-in for setup of a #ParameterRange evaluation to watch
* the processing of a single load peak, using the number of

View file

@ -7174,7 +7174,7 @@ Later on we expect a distinct __query subsystem__ to emerge, presumably embeddin
&amp;rarr; QuantiserImpl</pre>
</div>
<div title="Scheduler" creator="Ichthyostega" modifier="Ichthyostega" created="202304140131" modified="202312281735" tags="Rendering spec draft" changecount="29">
<div title="Scheduler" creator="Ichthyostega" modifier="Ichthyostega" created="202304140131" modified="202404081719" tags="Rendering spec draft" changecount="31">
<pre>//Invoke and control the dependency and time based execution of [[render jobs|RenderJob]]//
The Scheduler acts as the central hub in the implementation of the RenderEngine and coordinates the //processing resources// of the application. Regarding architecture, the Scheduler is located in the Vault-Layer and //running// the Scheduler is equivalent to activating the »Vault Subsystem«. An EngineFaçade acts as entrance point, providing high-level render services to other parts of the application: [[render jobs|RenderJob]] can be activated under various timing and dependency constraints. Internally, the implementation is organised into two layers:
;Layer-2: Coordination
@ -7213,9 +7213,22 @@ The Scheduler is now considered an implementation-level facility with an interfa
&amp;rarr; [[Memory|SchedulerMemory]]
&amp;rarr; [[Workers|SchedulerWorker]]
&amp;rarr; [[Internals|SchedulerProcessing]]
&amp;rarr; [[Behaviour|SchedulerBehaviour]]
&amp;rarr; [[Testing|SchedulerTest]]
</pre>
</div>
<div title="SchedulerBehaviour" creator="Ichthyostega" modifier="Ichthyostega" created="202404081716" modified="202404081717" tags="Rendering operational draft" changecount="6">
<pre>//Characteristic behaviour traits of the [[Scheduler]] implementation//
The design of the scheduler was chosen to fulfil some fundamental requirements..
* flexibility to accommodate a wide array of processing patterns
* direct integration of some notion of //dependency//
* ability to be re-triggered by external events
* reactive, but not over-reactive response to load peaks
* ability to withstand extended periods of excessive overload
* roughly precise timing with a margin of ≈ ''5''ms
The above list immediately indicates that this scheduler implementation is not oriented towards high throughput or extremely low latency, and thus can be expected to exhibit some //traits of response and behaviour.// These traits were confirmed and further investigated in the efforts for [[stress testing|SchedulerTest]] of the new Scheduler implementation. {{red{As of 4/2024}}} it remains to be seen, if the characteristics of the chosen approach are beneficial or even detrimental to the emerging actual usage -- it may well turn out that some adjustments must be made or even a complete rewrite of the Scheduler may be necessary.
</pre>
</div>
<div title="SchedulerLoadControl" creator="Ichthyostega" modifier="Ichthyostega" created="202310240240" modified="202311010317" tags="Rendering operational spec draft" changecount="60">
<pre>The scheduling mechanism //requires active control of work parameters to achieve good performance on average.//
In a nutshell, the scheduler arranges planned [[render activities|RenderActivity]] onto a time axis -- and is complemented by an [[active »work force«|SchedulerWorker]] to //pull and retrieve// the most urgent next task when free processing capacity becomes available. This arrangement shifts focus from the //management of tasks// towards the //management of capacity// -- which seems more adequate, given that capacity is scarce while tasks are abundant, yet limited in size and processed atomically.
@ -7304,8 +7317,8 @@ The primary scaling effects exploited to achieve this level of performance are t
&amp;rarr; [[Scheduler performance testing|SchedulerTest]]
</pre>
</div>
<div title="SchedulerProcessing" creator="Ichthyostega" modifier="Ichthyostega" created="202312281750" modified="202312281756" tags="Rendering operational draft" changecount="5">
<pre>At first sight, the internals of [[Activity|RenderActivity]] processing may seem overwhelmingly complex -- especially since there is no active »processing loop« which might serve as a starting point for the understanding. It is thus necessary to restate the working mode of the Scheduler: it is an //accounting and direction service// for the //active// [[render workers|SchedulerWorker]]. Any processing happens stochastically and is driven by events
<div title="SchedulerProcessing" creator="Ichthyostega" modifier="Ichthyostega" created="202312281750" modified="202404081703" tags="Rendering operational draft" changecount="6">
<pre>At first sight, the internals of [[Activity|RenderActivity]] processing may seem overwhelmingly complex -- especially since there is no active »processing loop« which might serve as a starting point for the understanding. It is thus necessary to restate the working mode of the Scheduler: it is an //accounting and direction service// for the //active// [[render workers|SchedulerWorker]]. Any processing happens stochastically and is driven by various kinds of events --
* a //worker// becoming ready to perform further tasks
* an external //IO event// {{red{12/23 only planned yet}}}
* a //planning job// to add new elements to the schedule
@ -7327,7 +7340,7 @@ The last point highlights a //circular structure:// the planning job itself was
The way other parts of the system are built, requires us to obtain a guaranteed knowledge of some job's termination. It is possible to obtain that knowledge with some limited delay, but it nees to be absoultely reliable (violations leading to segfault). The requirements stated above assume this can be achieved through //jobs with guaranteed execution.// Alternatively we could consider installing specific callbacks -- in this case the scheduler itself has to guarantee the invocation of these callbacks, even if the corresponding job fails or is never invoked. It doesn't seem there is any other option.
</pre>
</div>
<div title="SchedulerTest" creator="Ichthyostega" modifier="Ichthyostega" created="202312281814" modified="202401022341" tags="Rendering operational draft" changecount="9">
<div title="SchedulerTest" creator="Ichthyostega" modifier="Ichthyostega" created="202312281814" modified="202404081720" tags="Rendering operational draft" changecount="11">
<pre>With the Scheduler testing effort [[#1344|https://issues.lumiera.org/ticket/1344]], several goals are pursued
* by exposing the new scheduler implementation to excessive overload, its robustness can be assessed and defects can be spotted
* with the help of a systematic, calibrated load, characteristic performance limits and breaking points can be established
@ -7363,6 +7376,8 @@ The point of departure for any stress testing is to show that the subject is res
A method to determine such a »''breaking point''« in a systematic way relies on the //synthetic calculation load// mentioned above, the {{{TestChainLoad}}}. Using a simplified model of expected computation expense, a timing grid for scheduling can be established, which is then //scaled and condensed// to provoke loss of control in the Scheduler -- a condition that can be determined by statistical observation: since the process of scheduling contains an element of //essential randomness,// persistent overload will be indicated by an increasing variance of the overall runtime, and a departure from the nominal runtime of the executed schedule. This consideration leads to a formalised condition, which can be used to control a //binary search// to find the breaking point in terms of a //critical stress factor.//
Observing this breaking point in correlation with various load patterns will unveil performance characteristics and weak spots of the implementation.
&amp;rarr; [[Scheduler behaviour traits|SchedulerBehaviour]]
</pre>
</div>
<div title="SchedulerWorker" creator="Ichthyostega" modifier="Ichthyostega" created="202309041605" modified="202312281745" tags="Rendering operational spec draft" changecount="21">

View file

@ -111018,7 +111018,8 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</html></richcontent>
</node>
<node CREATED="1704766425859" ID="ID_819162648" MODIFIED="1704766437260" TEXT="geeignetes Last-Pattern aufbauen">
<node COLOR="#435e98" CREATED="1704766438235" FOLDED="true" ID="ID_49179977" MODIFIED="1704915284991" TEXT="Idee: &#xfc;bers&#xe4;ttigte Seeds + Breiten-Limitierung">
<node COLOR="#435e98" CREATED="1704766438235" FOLDED="true" ID="ID_49179977" MODIFIED="1712595247094" TEXT="Idee: &#xfc;bers&#xe4;ttigte Seeds + Breiten-Limitierung">
<linktarget COLOR="#4c5ab8" DESTINATION="ID_49179977" ENDARROW="Default" ENDINCLINATION="-515;1146;" ID="Arrow_ID_640223049" SOURCE="ID_1751068516" STARTARROW="None" STARTINCLINATION="-64;-3;"/>
<icon BUILTIN="idea"/>
<node CREATED="1704849761430" ID="ID_973472982" MODIFIED="1705011573250" TEXT="Graph-1: massiv-vernetzt">
<node CREATED="1704849789603" ID="ID_1248796850" MODIFIED="1704850126462" STYLE="bubble">
@ -111196,7 +111197,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="stop-sign"/>
</node>
</node>
<node COLOR="#338800" CREATED="1707697757045" ID="ID_1084113416" MODIFIED="1708651346551" TEXT="Instrumentierung im Job &#x27fc; effektive Concurrenvcy">
<node COLOR="#338800" CREATED="1707697757045" FOLDED="true" ID="ID_1084113416" MODIFIED="1712594810554" TEXT="Instrumentierung im Job &#x27fc; effektive Concurrenvcy">
<icon BUILTIN="button_ok"/>
<node CREATED="1707753850583" ID="ID_974443691" MODIFIED="1707753886880" TEXT="beide Instrumentierungen kann man hier gemeinsam machen">
<icon BUILTIN="idea"/>
@ -111941,7 +111942,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</html></richcontent>
</node>
</node>
<node COLOR="#338800" CREATED="1708652417482" ID="ID_350523685" MODIFIED="1712594063905" TEXT="brauche daf&#xfc;r ein anderes Me&#xdf;werkzeug">
<node COLOR="#338800" CREATED="1708652417482" FOLDED="true" ID="ID_350523685" MODIFIED="1712595012123" TEXT="brauche daf&#xfc;r ein anderes Me&#xdf;werkzeug">
<icon BUILTIN="yes"/>
<node CREATED="1708652645156" ID="ID_1558350785" MODIFIED="1708652664818" TEXT="&#xbb;ParameterRangeBench&#xab;">
<icon BUILTIN="info"/>
@ -112048,25 +112049,6 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node CREATED="1712239286828" ID="ID_24606608" MODIFIED="1712239292967" TEXT="Me&#xdf;-Anordnung">
<node CREATED="1712239307017" ID="ID_766419855" MODIFIED="1712239339117" TEXT="Scheduler einmalig beladen"/>
<node CREATED="1712239325075" ID="ID_1203654071" MODIFIED="1712239342970" TEXT="Abarbeitung dieser Last beobachtet"/>
<node CREATED="1712239349235" ID="ID_430565338" MODIFIED="1712239370596" TEXT="typischerweise: isolierte Nodes + &#xdc;berlast">
<icon BUILTIN="idea"/>
<node CREATED="1712239372216" ID="ID_291008354" MODIFIED="1712241669759" TEXT="ist aber flexibel"/>
<node CREATED="1712239376735" ID="ID_1372923577" MODIFIED="1712241693538" TEXT="tats&#xe4;hchlicher Kontroll-Parameter frei">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
...und was dieser Kontroll-Parameter tats&#228;chlich ist, wird allein durch das Setup festgelegt &#8212; denn dies erzeugt sowohl <i>jedesmal </i>eine neue Topologie
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1712241515362" ID="ID_326943240" MODIFIED="1712241527541" TEXT="kann durchaus auch regul&#xe4;res Schedule sein"/>
</node>
</node>
<node COLOR="#338800" CREATED="1710079791943" ID="ID_1402055509" MODIFIED="1712594169086" TEXT="Integration der Auswertung und Darstellung">
<linktarget COLOR="#3486b2" DESTINATION="ID_1402055509" ENDARROW="Default" ENDINCLINATION="-776;46;" ID="Arrow_ID_397225736" SOURCE="ID_1781115298" STARTARROW="None" STARTINCLINATION="-165;-9;"/>
<icon BUILTIN="button_ok"/>
@ -114850,8 +114832,7 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
Denn es gibt stets einige wenige <i>ganz dramatische Ausrei&#223;er, </i>die sonst die Skala so verschieben w&#252;rden, da&#223; man die eigentlichen Me&#223;werte nicht mehr sieht; ich m&#252;&#223;te also eigens wieder Anpassungs-Code schreiben, und mir eine Heuristik einfallen lassen, um die Skala zu kappen &#8212; unn&#246;tiger Aufwand f&#252;r eine nebenbei mit aufgenommene Gr&#246;&#223;e
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1712593740845" ID="ID_479430012" MODIFIED="1712593891254" TEXT="und au&#xdf;erdem: das sagt wenig &#xfc;ber die &#xbb;Arbeitsphase&#xab; aus">
<richcontent TYPE="NOTE"><html>
@ -114863,8 +114844,7 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
...denn der Umstand, da&#223; der Overhead / Job weitgehend konstant ist, zeigt, da&#223; wir hier einen separaten Setup-Effekt haben, vermutlich n&#228;mlich vor allem die Job-Planungs-Zeit. Da wir demgegen&#252;ber <i>in der aktiven Phase sehr gut linear sind, </i>kann man diesen zus&#228;tzlichen Overhead zun&#228;chst mal als Artefakt der Me&#223;anordnung beiseite lassen (und sp&#228;ter dann mal eigens untersuchen)
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
</node>
@ -115161,6 +115141,26 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
</node>
</node>
</node>
<node CREATED="1712239286828" ID="ID_24606608" MODIFIED="1712239292967" TEXT="Me&#xdf;-Anordnung">
<node CREATED="1712239307017" ID="ID_766419855" MODIFIED="1712239339117" TEXT="Scheduler einmalig beladen"/>
<node CREATED="1712239325075" ID="ID_1203654071" MODIFIED="1712239342970" TEXT="Abarbeitung dieser Last beobachtet"/>
<node CREATED="1712239349235" ID="ID_430565338" MODIFIED="1712595553285" TEXT="typischerweise: isolierte Nodes + &#xdc;berlast">
<linktarget COLOR="#4861c1" DESTINATION="ID_430565338" ENDARROW="Default" ENDINCLINATION="-805;54;" ID="Arrow_ID_1774826239" SOURCE="ID_1917510294" STARTARROW="None" STARTINCLINATION="373;-26;"/>
<icon BUILTIN="idea"/>
<node CREATED="1712239372216" ID="ID_291008354" MODIFIED="1712241669759" TEXT="ist aber flexibel"/>
<node CREATED="1712239376735" ID="ID_1372923577" MODIFIED="1712241693538" TEXT="tats&#xe4;hchlicher Kontroll-Parameter frei">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
...und was dieser Kontroll-Parameter tats&#228;chlich ist, wird allein durch das Setup festgelegt &#8212; denn dies erzeugt sowohl <i>jedesmal </i>eine neue Topologie
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1712241515362" ID="ID_326943240" MODIFIED="1712241527541" TEXT="kann durchaus auch regul&#xe4;res Schedule sein"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1708744078861" ID="ID_1023448351" MODIFIED="1708744085468" TEXT="Integration / Untersuchungen">
<icon BUILTIN="pencil"/>
<node CREATED="1708744086675" ID="ID_551606292" MODIFIED="1708744105373" TEXT="erster Me&#xdf;lauf">
@ -115308,7 +115308,7 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
<node CREATED="1709917609861" ID="ID_1607140185" MODIFIED="1709917789356" TEXT="jede Node prunen...">
<icon BUILTIN="idea"/>
</node>
<node COLOR="#435e98" CREATED="1709917623434" ID="ID_361282824" MODIFIED="1709946821083" TEXT="Problem: die letzte Node bekommt doch eine Verbindung">
<node COLOR="#435e98" CREATED="1709917623434" FOLDED="true" ID="ID_361282824" MODIFIED="1712595107593" TEXT="Problem: die letzte Node bekommt doch eine Verbindung">
<icon BUILTIN="messagebox_warning"/>
<node COLOR="#435e98" CREATED="1709942563557" ID="ID_446879015" MODIFIED="1709946418522" TEXT="woran liegt das nochmal?">
<icon BUILTIN="help"/>
@ -115413,6 +115413,37 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
<icon BUILTIN="pencil"/>
<node CREATED="1704915315663" ID="ID_1269775708" MODIFIED="1704915353923" TEXT="Standard-Aufbau">
<icon BUILTIN="info"/>
<node CREATED="1712595168957" ID="ID_1322573597" MODIFIED="1712595178892" TEXT="Last-Pattern">
<node CREATED="1712595181747" ID="ID_1751068516" MODIFIED="1712595247094" TEXT="spezielle &#xbb;kleine Graphen&#xab;">
<arrowlink COLOR="#4c5ab8" DESTINATION="ID_49179977" ENDARROW="Default" ENDINCLINATION="-515;1146;" ID="Arrow_ID_640223049" STARTARROW="None" STARTINCLINATION="-64;-3;"/>
<node CREATED="1712595253643" ID="ID_1495672824" MODIFIED="1712595270237" TEXT="diese enthalten einige wenige Dependencies"/>
<node CREATED="1712595270814" ID="ID_1695952418" MODIFIED="1712595286555" TEXT="und typischerweise reproduziert sich die Struktur verschachtelt"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1712595287407" ID="ID_1098867823" MODIFIED="1712595304821" TEXT="hier besteht das Problem der Breiten-Limitierung">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1712595306060" ID="ID_1687865117" MODIFIED="1712595325545" TEXT="zum Einen sind die Graphen u.U nicht breit genug, um alle Kerne auszulasten"/>
<node CREATED="1712595326353" ID="ID_1705802577" MODIFIED="1712595355025" TEXT="andererseits behindert eine feste (kleine) Breiten-Limitierung die Entfaltung der Struktur"/>
<node CREATED="1712595355774" ID="ID_1016902283" MODIFIED="1712595464915" TEXT="zudem gilt: die Anzahl Kerne ist ein sehr limitierter Parameter">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...denn er ist stark von der Hardware abh&#228;ngig und i.d.R wenig variierbar, und oft gibt es noch weitere, interne Beschr&#228;nkungen (wie z.B. Hyperthreading, das eben doch nicht komplett transparent ist und mit Cache und Pipelining im Prozessor wechselwirkt)
</p>
</body>
</html>
</richcontent>
</node>
</node>
</node>
<node CREATED="1712595477173" ID="ID_1859129003" MODIFIED="1712595502366" TEXT="isolierte Einzeljobs">
<node CREATED="1712595503210" ID="ID_1917510294" MODIFIED="1712595559393" TEXT="&#xbb;kompakt&#xab; / &#xbb;dicht&#xab;">
<arrowlink COLOR="#4861c1" DESTINATION="ID_430565338" ENDARROW="Default" ENDINCLINATION="-805;54;" ID="Arrow_ID_1774826239" STARTARROW="None" STARTINCLINATION="373;-26;"/>
</node>
<node CREATED="1712595518473" ID="ID_1871408755" MODIFIED="1712595524139" TEXT="oder als &#xbb;load bursts&#xab;"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1704915323510" ID="ID_1549178834" MODIFIED="1704915348364" TEXT="1.Test">
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1704915326966" ID="ID_117301056" MODIFIED="1704915346470" TEXT="8 Kerne gleichm&#xe4;&#xdf;ige Last 500&#xb5;s">
@ -115522,7 +115553,7 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
<linktarget COLOR="#3a84b6" DESTINATION="ID_1350365350" ENDARROW="Default" ENDINCLINATION="-192;14;" ID="Arrow_ID_980960219" SOURCE="ID_909211409" STARTARROW="None" STARTINCLINATION="118;-27;"/>
</node>
</node>
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#a50125" CREATED="1707609859180" ID="ID_1719205806" MODIFIED="1707668086255" TEXT="Problem: bin&#xe4;re Suche greift nicht">
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#a50125" CREATED="1707609859180" FOLDED="true" ID="ID_1719205806" MODIFIED="1712595086004" TEXT="Problem: bin&#xe4;re Suche greift nicht">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1707609897512" ID="ID_72695158" MODIFIED="1707610206793" TEXT="zun&#xe4;chst einmal: sie kann gar nicht greifen ohne Last oder Basis-Aufwand">
<richcontent TYPE="NOTE"><html>
@ -116397,6 +116428,9 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1702417929236" ID="ID_1002777321" MODIFIED="1704287870161" TEXT="SchedulerProcessing">
<icon BUILTIN="pencil"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1712595711766" ID="ID_1469323006" MODIFIED="1712595717814" TEXT="SchedulerBehaviour">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1702417945750" ID="ID_219061374" MODIFIED="1704287870162" TEXT="SchedulerTest">
<icon BUILTIN="pencil"/>
</node>