Block-Flow: initial draft of ExtentFamily storage
using a simple yet performant data structure. Not clear yet if this approach is sustainable - assuming that no value initialisation happens for POD payload - performance trade-off growth when in wrapped-state vs using a list
This commit is contained in:
parent
23a6fbdf4f
commit
022d40a8cf
4 changed files with 162 additions and 18 deletions
|
|
@ -50,6 +50,9 @@
|
|||
//#include "lib/util.hpp"
|
||||
|
||||
//#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
|
||||
namespace vault{
|
||||
|
|
@ -64,14 +67,43 @@ namespace mem {
|
|||
* @todo WIP-WIP 7/2023
|
||||
* @see NA_test
|
||||
*/
|
||||
template<typename T, size_t siz>
|
||||
class ExtentFamily
|
||||
: util::NonCopyable
|
||||
{
|
||||
using Storage = std::array<T,siz>;
|
||||
|
||||
struct Extent
|
||||
: std::unique_ptr<Storage>
|
||||
{
|
||||
/**
|
||||
* @note default ctor immediately allocates the full storage,
|
||||
* but uses default initialisation rsp. no initialisation
|
||||
* in case the payload type T is a POD
|
||||
*/
|
||||
Extent()
|
||||
: std::unique_ptr<Storage>{new Storage}
|
||||
{ }
|
||||
};
|
||||
using Extents = std::vector<Extent>;
|
||||
|
||||
Extents extents_;
|
||||
|
||||
size_t start_,after_;
|
||||
|
||||
public:
|
||||
explicit
|
||||
ExtentFamily()
|
||||
ExtentFamily(size_t initialCnt =0)
|
||||
: extents_{initialCnt}
|
||||
, start_{0}
|
||||
, after_{initialCnt}
|
||||
{ }
|
||||
|
||||
void
|
||||
reserve (size_t expectedMaxExtents)
|
||||
{
|
||||
extents_.reserve (expectedMaxExtents);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ namespace test {
|
|||
void
|
||||
simpleUsage()
|
||||
{
|
||||
ExtentFamily extents;
|
||||
ExtentFamily<int, 10> extents{5};
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6183,7 +6183,7 @@ This is the core service provided by the player subsystem. The purpose is to cre
|
|||
:any details of this processing remain opaque for the clients; even the player subsystem just accesses the EngineFaçade
|
||||
</pre>
|
||||
</div>
|
||||
<div title="PlaybackVerticalSlice" creator="Ichthyostega" modifier="Ichthyostega" created="202303272236" modified="202307031635" tags="overview impl discuss draft" changecount="29">
|
||||
<div title="PlaybackVerticalSlice" creator="Ichthyostega" modifier="Ichthyostega" created="202303272236" modified="202307032218" tags="overview impl discuss draft" changecount="31">
|
||||
<pre>//Integration effort to promote the development of rendering, playback and video display in the GUI//
|
||||
This IntegrationSlice was started in {{red{2023}}} as [[Ticket #1221|https://issues.lumiera.org/ticket/1221]] to coordinate the completion and integration of various implementation facilities, planned, drafted and built during the last years; this effort marks the return of development focus to the lower layers (after years of focussed UI development) and will implement the asynchronous and time-bound rendering coordinated by the [[Scheduler]] in the [[Vault|Vault-Layer]]
|
||||
|
||||
|
|
@ -6202,14 +6202,14 @@ __May.23__: taking a //prototyping approach// now, since further development was
|
|||
* ✔ augment the {{{DummyJob}}} to allow tracing Job invocations in tests
|
||||
* ✔ build a {{{MockJobTicket}}} on top, implemented as subclass of the actual JobTicket
|
||||
* ✔ build a {{{MockSegmentation}}} to hold onto ~JobTickets, which can be created as Mock
|
||||
* ✔define a simple specification language (based on the existing {{{GenNode}}}-DSL to define segments, tickets and prerequisite jobs
|
||||
* ✔ define a simple specification language (based on the existing {{{GenNode}}}-DSL to define segments, tickets and prerequisite jobs
|
||||
* ✔ implement a »~Split-Splice« algorithm for &rarr; SegmentationChange, rigged accordingly to generate a mocked Segementation for now
|
||||
* ✔ create a testbed to assemble a JobPlanningPipeline step by step (&rarr; [[#920|https://issues.lumiera.org/ticket/920]] and [[#1275|https://issues.lumiera.org/ticket/1275|]])
|
||||
|
||||
__June23__: building upon this prototyping approach, the dispatcher pipeline could be rearranged in the form of a pipeline builder, allowing to retract the originally used implementation scheme based on »Monads«. The implementation of the Dispatcher is complete, yet the build up of the [[»Render Drive« #1301|https://issues.lumiera.org/ticket/1301]] could not reasonably be completed, due to lack of a clear-shaped ''Scheduler interface''.
|
||||
|
||||
__July23__: this leads to a shift of work focus towards implementing the [[Scheduler]] itself.
|
||||
The Scheduler will be structured into two Layers, where the lower layer is implemented as //priority queue// (using the STL). So the most tricky part to solve is the representation of //dependencies// between jobs, with the possible extension to handling IO operations asynchronously. Analysis and planning of the implementation indicate that the [[scheduler memory managment|SchedulerMemory]] can be based on //Extents//, which are interpreted as »Epochs« with a deadline. These considerations imply the next steps for building up the Scheduler functionality
|
||||
The Scheduler will be structured into two Layers, where the lower layer is implemented as //priority queue// (using the STL). So the most tricky part to solve is the representation of //dependencies// between jobs, with the possible extension to handling IO operations asynchronously. Analysis and planning of the implementation indicate that the [[scheduler memory managment|SchedulerMemory]] can be based on //Extents//, which are interpreted as »Epochs« with a deadline. These considerations imply what steps to take next for building up Scheduler functionality and memory management required for processing a simple job
|
||||
* 🗘 build a first working draft for the {{{BlockFlow}}} allocation scheme [[#1311|https://issues.lumiera.org/ticket/1311]]
|
||||
* ⌛ define and cover the basic [[Activities|RenderActivity]] necessary to implement a plain-simple-Job (without dependencies)
|
||||
* ⌛ pass such an Activity through the two layers of the Scheduler
|
||||
|
|
@ -7054,10 +7054,10 @@ Later on we expect a distinct __query subsystem__ to emerge, presumably embeddin
|
|||
|
||||
&rarr; QuantiserImpl</pre>
|
||||
</div>
|
||||
<div title="Scheduler" creator="Ichthyostega" modifier="Ichthyostega" created="202304140131" modified="202307031603" tags="Rendering spec draft" changecount="9">
|
||||
<div title="Scheduler" creator="Ichthyostega" modifier="Ichthyostega" created="202304140131" modified="202307032227" tags="Rendering spec draft" changecount="12">
|
||||
<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 segregated into two layers
|
||||
;Layer-2: Control
|
||||
;Layer-2: Coordination
|
||||
:maintains a network of interconnected [[activities|RenderActivity]], tracks dependencies and observes timing constraints
|
||||
;Layer-1: Invocation
|
||||
:operates a low-level priority scheduling mechanism for time-bound execution of [[activities|RenderActivity]]
|
||||
|
|
@ -7073,25 +7073,29 @@ The time-based ordering and prioritisation of [[render activities|RenderActivity
|
|||
!Usage pattern
|
||||
The [[Language of render activities|RenderActivity]] forms the interface to the scheduler -- new activities are defined as //terms// and handed over to the scheduler. This happens as part of the ongoing job planning activities -- and thus will be performed //from within jobs managed by the scheduler.// Thus the access to the scheduler happens almost entirely from within the scheduler's realm itself, and is governed by the usage scheme of the [[Workers|SchedulerWorker]].
|
||||
|
||||
These ''Worker Threads'' will perform actual render activities most of the time (or be idle). However -- idle workers contend for new work, and for doing so, they //also perform the internal scheduler management activities.// As a consequence, all Scheduler coordination and [[memory management|SchedulerMemory]] is ''performed non-concurrent'': only a single Worker can acquire the {{{GroomingToken}}} and will then perform managment work until the next render activity is encountered.
|
||||
These ''Worker Threads'' will perform actual render activities most of the time (or be idle). However -- idle workers contend for new work, and for doing so, they //also perform the internal scheduler management activities.// As a consequence, all Scheduler coordination and [[memory management|SchedulerMemory]] is ''performed non-concurrent'': only a single Worker can acquire the {{{GroomingToken}}} and will then perform managment work until the next render activity is encountered at the top side of the //priority queue.//
|
||||
|
||||
&rarr; [[Activity|RenderActivity]]
|
||||
&rarr; [[Memory|SchedulerMemory]]
|
||||
&rarr; [[Workers|SchedulerWorker]]
|
||||
</pre>
|
||||
</div>
|
||||
<div title="SchedulerMemory" creator="Ichthyostega" modifier="Ichthyostega" created="202307031622" tags="Rendering operational draft" changecount="1">
|
||||
<pre>//The Scheduler uses an »Extent« based memory management scheme known as ''BlockFlow''.//
|
||||
The organisation of rendering happens in terms of [[Activities|RenderActivity]], which may bound by //dependencies// and limited by //deadlines.// For the operational point of view this implies that a sequence of allocations must be maintained to „flow through the Scheduler“ -- in fact, only references to these {{{Activity}}} records are passed, while the actual descriptors reside at fixed memory locations. This is essential to model dependencies and conditional execution structures efficiently. At some point however, any {{{Activity}}} record will either be //performed// or //obsoleted// -- and this leads to the idea of managing the allocations in memory extents termed as »Epochs«
|
||||
<div title="SchedulerMemory" creator="Ichthyostega" modifier="Ichthyostega" created="202307031622" modified="202307032243" tags="Rendering operational draft" changecount="11">
|
||||
<pre>//The Scheduler uses an »Extent« based memory management scheme known as {{{BlockFlow}}}.//
|
||||
The organisation of rendering happens in terms of [[Activities|RenderActivity]], which may bound by //dependencies// and limited by //deadlines.// For the operational point of view this implies that a sequence of allocations must be able to „flow through the Scheduler“ -- in fact, only references to these {{{Activity}}}-records are passed, while the actual descriptors reside at fixed memory locations. This is essential to model the dependencies and conditional execution structures efficiently. At some point however, any {{{Activity}}}-record will either be //performed// or //obsoleted// -- and this leads to the idea of managing the allocations in //extents// of memory here termed as »Epochs«
|
||||
* a new Activity is planted into a suitable //Epoch,// based on its deadline
|
||||
* it is guaranteed to sit at a fixed memory location while it potentially can be activated
|
||||
* based on the deadlines, at some point a complete strike of activities can be reasoned to be //obsolete.//
|
||||
* this allows to discard a complete Extent without any further checks and processing (trivial destructors!)
|
||||
* it is guaranteed to sit at a fixed memory location while it can be activated potentially
|
||||
* based on the deadlines, at some point a complete strike of activities can be reasoned to be //obsoleted.//
|
||||
* this allows to discard a complete Extent //without any further checks and processing// (assuming trivial destructors!)
|
||||
|
||||
!Safeguards
|
||||
This is a rather fragile composition and chosen here for performance reasons; while activities are interconnected, there memory locations are adjacent, improving cache coherence. Moreover, most of the dependency processing and managing of activities happens single-threaded, while some [[worker|SchedulerWorker]] holds the {{{GroomingToken}}}; so most of the processing is local and does not require memory barriers.
|
||||
This is a rather fragile composition and chosen here for performance reasons; while activities are interconnected, their memory locations are adjacent, improving cache locality. Moreover, most of the dependency processing and managing of activities happens single-threaded, while some [[worker|SchedulerWorker]] holds the {{{GroomingToken}}}; so most of the processing is local and does not require memory barriers.
|
||||
|
||||
Unfortunately this also implies that most safety barriers of the C++ language are removed or circumvented. A strict processing regime must be established, with clear rules as to when activities may be accessed.
|
||||
Unfortunately this tricky arrangement also implies that many safety barriers of the C++ language are circumvented. A strict processing regime must be established, with clear rules as to when activities may, or may no longer be accessed.
|
||||
* each »Epoch« gets an associated //deadline//
|
||||
* when the next [[job|RenderJob]] processed by a worker starts //after this Epoch's deadline//, the worker //has left the Epoch.//
|
||||
* when all workers have left an Epoch, only ''pending async IO tasks'' need to be considered, since such IO task can always be delayed for an extended period of time. For an IO task, buffers need to be prepared, and those buffers are indirectly tied to the job depending on them.
|
||||
* ⟹ thus a count of pending IO activities must be maintained //for each Epoch// -- implemented by the same mechanism also employed for dependencies between render jobs, namely a notification leading to decreasing a local counter
|
||||
* when all workers have left an Epoch, only ''pending async IO tasks'' need to be considered, since such IO task can always be delayed for an extended period of time. For an IO task, buffers need to be kept available, and those buffers are indirectly tied to the job depending on them.
|
||||
* ⟹ thus a count of pending IO activities must be maintained //for each Epoch// -- implemented by the same mechanism also employed for dependencies between render jobs, which is a notification message causing a local counter to be decremented.
|
||||
</pre>
|
||||
</div>
|
||||
<div title="SchedulerRequirements" modifier="Ichthyostega" created="201107080145" modified="201112171835" tags="Rendering spec draft discuss">
|
||||
|
|
|
|||
|
|
@ -78301,6 +78301,12 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node CREATED="1688394900403" ID="ID_1380392473" MODIFIED="1688394919878" TEXT="underlying sequence-of-extents">
|
||||
<icon BUILTIN="info"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1688434736501" ID="ID_1334906045" MODIFIED="1688434766802" TEXT="simpleUsage">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1688434743454" ID="ID_722620082" MODIFIED="1688434762609" TEXT="ExtentFamily erzeugen mit pre-Allocation">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688336697451" ID="ID_360159435" MODIFIED="1688337246569" TEXT="SchedulerActivity_test">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
|
|
@ -78535,6 +78541,18 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688398685028" ID="ID_1348599303" MODIFIED="1688398807927" TEXT="Anforderungen">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1688398688699" ID="ID_1432998672" MODIFIED="1688398701914" TEXT="stellt eine Sequenz von »Extents« bereit"/>
|
||||
<node CREATED="1688432466445" ID="ID_1473749393" MODIFIED="1688432494176">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
ein Extent ist ein <i>uninitialisierter </i>Speicherblock
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1688398703247" ID="ID_1790971931" MODIFIED="1688398726830" TEXT="die aktiven Extents sind geordnet und iterierbar"/>
|
||||
<node CREATED="1688398734470" ID="ID_1849160897" MODIFIED="1688398753155" TEXT="man kann „einen Weiteren“ belegen"/>
|
||||
<node CREATED="1688398760358" ID="ID_944914676" MODIFIED="1688398769143" TEXT="Extent kann freigegeben werden"/>
|
||||
|
|
@ -78548,12 +78566,90 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688398884005" ID="ID_1188543253" MODIFIED="1688398901314" TEXT="Basis-Struktur">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1688432746255" ID="ID_880122043" MODIFIED="1688432851088" TEXT="Entscheidung: die Größe ist eine compile-time-Konstante">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Begründung:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Performance...
|
||||
</li>
|
||||
<li>
|
||||
mehr Dynamik wird gar nicht benötigt, da das BlockFlow-Schema noch die Dauer einer Epoche justieren kann
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node CREATED="1688435528483" ID="ID_8576020" MODIFIED="1688435554882" TEXT="Entscheidung: es wird ein Payload-Typ für den Inhalt der Extents festgelegt">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1688432504244" ID="ID_1241185228" MODIFIED="1688434715080" TEXT="Extent (Storage)">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688432516234" ID="ID_615463720" MODIFIED="1688432527931" TEXT="Anfroderung: keine Initialisierung">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1688432531628" ID="ID_370870831" MODIFIED="1688432652286" TEXT="wichtig für die Performance">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node CREATED="1688432597371" ID="ID_254731124" MODIFIED="1688432648521" TEXT="ist gewährleistet für alle POD und Arrays von Basistypen">
|
||||
<icon BUILTIN="info"/>
|
||||
</node>
|
||||
<node CREATED="1688432635374" ID="ID_213229192" MODIFIED="1688432646377" TEXT="std::array ist ein POD">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node CREATED="1688432677832" ID="ID_409669482" MODIFIED="1688432698306" TEXT="Syntax: kein Initialiser, und ein impliziter default-ctor"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1688437935976" ID="ID_518652809" MODIFIED="1688438261107" TEXT="Entscheidung: vom Payload-Typ abhängig machen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
das heißt: es findet zwar eine default-Initialisierung statt, aber für einen Objekt-Typ bedeutet das <i>value-Initialisierung der Member.</i> Nur falls der Payload-Typ ein POD ist, findet keine Initialisierung statt — und ich hoffe, daß der Optimizer das checkt
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<linktarget COLOR="#b85283" DESTINATION="ID_518652809" ENDARROW="Default" ENDINCLINATION="587;31;" ID="Arrow_ID_463215029" SOURCE="ID_1531653683" STARTARROW="None" STARTINCLINATION="897;-29;"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1688432712542" ID="ID_849183361" MODIFIED="1688435612692" TEXT="Basis std::unique_ptr<array<T,siz>>">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1688433893319" ID="ID_666220506" MODIFIED="1688434720661" TEXT="default-ctor macht sofort die Allokation">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1688432864248" ID="ID_1390525681" MODIFIED="1688435636832" TEXT="Extents gehalten als vector<unique_ptr<...>>">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688398888563" ID="ID_1767596073" MODIFIED="1688398901315" TEXT="Iteration">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1688437541022" ID="ID_1493417420" MODIFIED="1688437566889" TEXT="kann man überhaupt iterieren ohne einen TransformIterator zu verwenden?">
|
||||
<icon BUILTIN="help"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688398893220" ID="ID_675575195" MODIFIED="1688398901316" TEXT="belegen / freigeben">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688437691137" ID="ID_292063242" MODIFIED="1688437712023" TEXT="prüfen auf ausreichende Reserve">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688437762175" ID="ID_1456790340" MODIFIED="1688437794274" TEXT="sonst: Allokation erweitern">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688437770295" ID="ID_867206595" MODIFIED="1688437792757" TEXT="falls am Ende">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688437784470" ID="ID_797852741" MODIFIED="1688437792758" TEXT="falls wrap-around">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -79307,9 +79403,21 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1680563509728" ID="ID_1883500842" MODIFIED="1684869810400" TEXT="Scheduler">
|
||||
<icon BUILTIN="stop"/>
|
||||
<node CREATED="1688438164169" ID="ID_1339299906" MODIFIED="1688438167334" TEXT="Funktionalität">
|
||||
<node CREATED="1680563512563" ID="ID_960191744" MODIFIED="1680563516470" TEXT="Layer-2"/>
|
||||
<node CREATED="1680563517255" ID="ID_1104189783" MODIFIED="1680563519264" TEXT="Layer-1"/>
|
||||
</node>
|
||||
<node CREATED="1688438172401" ID="ID_1302126473" MODIFIED="1688438176429" TEXT="Memory-Manager"/>
|
||||
<node CREATED="1688438177472" ID="ID_854658770" MODIFIED="1688438183516" TEXT="Weiterentwicklung">
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1688438184671" ID="ID_1971690047" MODIFIED="1688438194457" TEXT="Prüfen / messen">
|
||||
<icon BUILTIN="bell"/>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1688438197846" ID="ID_1531653683" MODIFIED="1688438261107" TEXT="findet für POD tatsächlich keine value-Initialisierung der Storage statt?">
|
||||
<arrowlink COLOR="#b85283" DESTINATION="ID_518652809" ENDARROW="Default" ENDINCLINATION="587;31;" ID="Arrow_ID_463215029" STARTARROW="None" STARTINCLINATION="897;-29;"/>
|
||||
<icon BUILTIN="help"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1512923629577" ID="ID_617347424" MODIFIED="1557498707237" TEXT="Backend">
|
||||
<node CREATED="1680565608115" ID="ID_1114884704" MODIFIED="1680565612050" TEXT="Hilfsmittel">
|
||||
|
|
|
|||
Loading…
Reference in a new issue