Library: draft standard case for actual memory allocation
- attempt to use the minimal possible storage for the management itself - rely on the `std::align()` function to do the actual placement
This commit is contained in:
parent
eeda3aaa56
commit
c623298ac8
2 changed files with 101 additions and 78 deletions
|
|
@ -44,19 +44,16 @@
|
|||
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/nocopy.hpp"
|
||||
#include "lib/sync-classlock.hpp"
|
||||
#include "lib/scoped-holder.hpp"
|
||||
#include "lib/scoped-holder-transfer.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <utility> ///////////////////OOO woot?
|
||||
#include <memory>
|
||||
|
||||
|
||||
|
||||
namespace lib {
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* A pile of objects sharing common allocation and lifecycle.
|
||||
* AllocationCluster owns a number of object families of various types.
|
||||
* Each of those contains a initially undetermined (but rather large)
|
||||
|
|
@ -100,6 +97,10 @@ namespace lib {
|
|||
AllocationCluster* mother_;
|
||||
};
|
||||
|
||||
/* maintaining the Allocation */
|
||||
void* storage_;
|
||||
size_t remain_;
|
||||
|
||||
public:
|
||||
AllocationCluster ();
|
||||
~AllocationCluster () noexcept;
|
||||
|
|
@ -109,7 +110,7 @@ namespace lib {
|
|||
TY&
|
||||
create (ARGS&& ...args)
|
||||
{
|
||||
return * new(allotMemory (sizeof(TY))) TY (std::forward<ARGS> (args)...);
|
||||
return * new(allot<TY>()) TY (std::forward<ARGS> (args)...);
|
||||
}
|
||||
|
||||
template<typename X>
|
||||
|
|
@ -141,16 +142,20 @@ namespace lib {
|
|||
* possibly claiming a new pool block.
|
||||
*/
|
||||
void*
|
||||
allotMemory (size_t bytes)
|
||||
allotMemory (size_t bytes, size_t alignment)
|
||||
{
|
||||
void* loc = std::align(alignment, bytes, storage_, remain_);
|
||||
if (loc)
|
||||
return loc;
|
||||
UNIMPLEMENTED ("actual memory management");
|
||||
///////////////////////////////////////////////////////////OOO claim next macro block
|
||||
}
|
||||
|
||||
template<typename X>
|
||||
X*
|
||||
allot (size_t cnt =1)
|
||||
{
|
||||
return static_cast<X*> (allotMemory (cnt * sizeof(X)));
|
||||
return static_cast<X*> (allotMemory (cnt * sizeof(X), alignof(X)));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -80694,8 +80694,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
An der Stelle habe ich nicht weiter analysiert, sondern einfach Heap-Allokationen gemacht; der Grund seinerzeit war, daß Christian den »Mempool« überall einführen wollte — ein Ansatz, den ich grundsätzlich unterstützte, wenngleich auch seine Implementierung zu einfach war, und ich damit diesen use-Case nicht sauber realisieren konnte. Damit unterblieben aber weitere Überlegungen zum Allocation-Trend
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1715625485709" ID="ID_323773842" MODIFIED="1715625503477" TEXT="zu viel Locking — und möglicherweise an der falschen Stelle"/>
|
||||
<node CREATED="1715625511889" HGAP="39" ID="ID_1920622182" MODIFIED="1715625840520" TEXT="Effizienz der Familien-Pools erscheint fragwürdig" VSHIFT="-29">
|
||||
|
|
@ -80708,8 +80707,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
damals hatte ich als Vorbild den <i>small-objects pool allocator </i>von Alexandrescu im Kopf; deshalb habe ich auch »Familien« von Objekten vorgesehen — ohne jedoch zu klären, ob und wie sich daraus ein Amortisierungs-Effekt ergibt. Nach gründlicherer Überlegung erscheint mir das als ein Widerspruch im Konzept, denn diese small-objects-Pools laufen ja auf ein Tiling mit fortlaufend stattfindedenden Allokationen hinaus; das ist exakt das Gegenteil von dem, was mir hier vorschwebt. Damit würden die Einzelpools nur Administrations-Overhead verursachen, der seine Vorteile überhaupt nicht ausspielen kann; stattdessen sollte besser in Betracht gezogen werden, alles heterogen, so wie es kommt, in größere Blöcke zu packen. Das Tiling würde damit auf einem größeren Level stattfinden, und wäre in den Basis-Allocator verlagert...
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1714870490954" ID="ID_433835630" MODIFIED="1714870505595" TEXT="Aufräumen">
|
||||
|
|
@ -80999,8 +80997,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
⟹ Konsequenz: zusätzlicher Template-Parameter für das<i> Spacing</i>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node COLOR="#5b280f" CREATED="1715532386464" ID="ID_1896451330" MODIFIED="1715532398219" TEXT="oder eben eine VTable wie in RefArray">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
|
|
@ -81064,8 +81061,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
oder man bekommt eine<i> implizite Runtime</i>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -81087,8 +81083,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
wenn die Daten „woanders“ liegen
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1715533317000" ID="ID_252143573" MODIFIED="1715533493572">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
|
|
@ -81100,8 +81095,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
⟹ das <b>Allocator-Problem</b> überträgt sich <b>komplett</b>  auf den Container selber
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
|
|
@ -81111,8 +81105,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
warum? weil man dann zwingend im Container selber einen »Slot« mit einem Functor oder Allocator-Pointer rumschleppt — oder doch wieder einen zusätzlichen Instanz-Typ-Tag
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -81144,8 +81137,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
⟹ bläht die Storage um 30% auf
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1715618955861" ID="ID_189897298" MODIFIED="1715619378057" TEXT="dann halt doch bloß Heap-Allokationen machen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
|
|
@ -81168,8 +81160,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1715620143727" ID="ID_828708828" MODIFIED="1715620159863" TEXT="Zugriff auf den Allocator per DI (statisch) oder Thread-local"/>
|
||||
<node CREATED="1715620242056" ID="ID_427769562" MODIFIED="1715620649844" TEXT="Spezieller Allocator mit Block-de-Allocation">
|
||||
|
|
@ -81182,8 +81173,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
...man verwendet <i>nur speziell im produktiven Einsatz im Node-Graph</i>  einen besonderen Allocator, der zwar den Destruktor aufruf, aber den Speicher nicht freigibt; alloziert wird immer in einen kompakten Block hinein, der dann auf der Basis der Prozeß-Kenntnis als Ganzes verworfen und neu verwendet wird.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="forward"/>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -81203,8 +81193,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
...weil std::vector zwar bereits alles bietet, aber eingebettet in sehr komplexen Code — im Besonderen dürfte es schwierig werden, das Thema on-demand-growth vs non-copyable zu umschiffen
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1715624963026" ID="ID_744219090" MODIFIED="1715624972411" TEXT="separaten Builder für die zwei Nutz-Muster">
|
||||
|
|
@ -81222,8 +81211,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
...das heißt, ich gehe mal davon aus, daß ich mit einer einzigen, dedizierten Implementierung erst mal den aktuellen Bedarf decken kann; daraus könnte allerdings später immer noch ein Concept gemacht werden, welches dann alternativ auch durch ScopedCollection oder durch eine embedded-storage-Lösung erfüllt werden kann.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -81242,8 +81230,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
heterogene Allokation in eine Sequenz größerer Blöcke; keinerlei de-Allokation und kein Locking
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1715625881800" ID="ID_1460908503" MODIFIED="1715626254822" TEXT="man könnte aber die bestehende Impl. erst mal ungesehen verwenden">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
|
|
@ -81269,8 +81256,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1715625901869" ID="ID_460237769" MODIFIED="1715626344549" TEXT="oder aber gleich ganz liegen lassen und bloß Heap-Allokationen machen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
|
|
@ -81282,8 +81268,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
...<i>wenn man schon </i>die bestehenden Implementierung nutzt (wohl wissend, daß ihre inhärenten Probleme erst mal nicht relevant sind), dann kann man genausogut <i>ganz auf blöd </i>sich auf den KISS-Standpunkt stellen und einfach Heap-Allokationen machen, denn die sind heutzutage verdammt effizient geworden
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1715625929114" ID="ID_704028431" MODIFIED="1715625953412">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
|
|
@ -81295,8 +81280,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
...und alles das läuft auf weitere <b>technische Schulden</b> hinaus
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1715626381670" ID="ID_365556330" MODIFIED="1715626396019" TEXT="Idee: den Allocation-Cluster unter gleichem Namen im Grund neu schreiben">
|
||||
|
|
@ -81312,8 +81296,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
...die allesamt mit dem Model + Player zu tun haben; einzige externe Verkoppelung ist der LinkedElements_test, und auch dieser stellt explizit einen Vorgriff auf die Verwendung im low-level-Model dar.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1715626599088" ID="ID_1068758723" MODIFIED="1715626653670" TEXT="das API ist schmal und könnte inkrementell umgestaltet werden">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
|
|
@ -81325,8 +81308,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
...da der davon abhängende Code <i>effektiv nur compilierbar ist, aber nicht lauffähig</i>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1715626710965" ID="ID_1722763351" MODIFIED="1715626721940" TEXT="die neue Lösung wäre in jedem Fall einfacher">
|
||||
<node CREATED="1715626738174" ID="ID_714358898" MODIFIED="1715626997202" TEXT="alles Locking fällt weg"/>
|
||||
|
|
@ -81341,8 +81323,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
let it crash — wenn tatsächlich eine Exception fliegt, ist es ziemlich wahrscheinlich, daß der ganze Cluster sowiso weggeworfen wird; wenn nicht, dann akzeptieren wir einfach toten Speicher.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1715626853846" ID="ID_540898270" MODIFIED="1715626985387">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
|
|
@ -81354,8 +81335,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
die Bedeutung ist <b>geringer geworden</b>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
|
|
@ -81365,8 +81345,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
seinerzeit habe ich im AllocationCluster etwas gesehen, daß pervasiv überall im Code verwendet wird, analog zum Mempool. Inzwischen stehe ich auf dem Standpunkt, daß für die meisten Allokationen der Standard-Heap-Allokator sowiso gut genug ist (oder man nutzt ohnehin den Stack oder eine statische Variable); spezielle Allokatoren sind nach meinem heutigen Verständnis nur noch sinnvoll, wenn sie extrem spezifisch sind
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -81382,8 +81361,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
...oder zumindest könnte man ein limitiertes Teil-Konzept umsetzen; mir fällt auf, daß diverse Methoden im Standard-Allocator inzwischen durch Traits ersetzt wurden.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<node CREATED="1715725369201" ID="ID_1600204256" MODIFIED="1715725381650" TEXT="tatsächlich ist es heutzutage sehr einfach"/>
|
||||
<node CREATED="1715725400796" ID="ID_1894647974" MODIFIED="1715725416576" TEXT="praktisch jeder custom-allocator kann standardkonform gemacht werden">
|
||||
<icon BUILTIN="idea"/>
|
||||
|
|
@ -81703,8 +81681,60 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1715725837111" ID="ID_1956366876" MODIFIED="1715725864907" TEXT="Basis-Allocator vorsehen">
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1715725837111" ID="ID_1956366876" MODIFIED="1715818720819" TEXT="Basis-Allocation vorsehen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#435e98" CREATED="1715817001701" ID="ID_315311831" MODIFIED="1715817053842" TEXT="wie einbinden?">
|
||||
<node COLOR="#5b280f" CREATED="1715817015550" ID="ID_116856376" MODIFIED="1715817030369" TEXT="als Standard-Allocator">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
</node>
|
||||
<node CREATED="1715817031505" ID="ID_892440156" MODIFIED="1715817051313" TEXT="weiterhin als feste Implementierungs-Entscheidung">
|
||||
<icon BUILTIN="forward"/>
|
||||
<node CREATED="1715817058766" ID="ID_1820924124" MODIFIED="1715817078576" TEXT="AllocationCluster ist keine generische Library-Klasse"/>
|
||||
<node CREATED="1715817079155" ID="ID_395981478" MODIFIED="1715817088157" TEXT="sondern eine sehr speziell gebundene Einrichtung"/>
|
||||
<node CREATED="1715817092113" ID="ID_1132434919" MODIFIED="1715817104459" TEXT="ein generischer Allocator würde in den Typ eingehen"/>
|
||||
<node CREATED="1715817106468" ID="ID_1098144156" MODIFIED="1715817115970" TEXT="...und das ist nur unnötige Komplikation"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1715818949821" ID="ID_1747630681" MODIFIED="1715818962407" TEXT="Thema: Alignment">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1715818964036" ID="ID_1917864530" MODIFIED="1715818999461" TEXT="bedeutet: der Offset wird justiert bis er auf einer Alignment-Grenze liegt"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1715819022774" ID="ID_541145684" MODIFIED="1715819026470" TEXT="Anforderungen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1715819037772" ID="ID_1987233619" MODIFIED="1715819050902" TEXT="soll selber mit dem absoluten Minimum an Storage auskommen"/>
|
||||
<node CREATED="1715819058921" ID="ID_895637699" MODIFIED="1715819099232" TEXT="muß zur de-Allokation eine Basis-Block-Kette navigieren"/>
|
||||
<node CREATED="1715819206460" ID="ID_897739837" MODIFIED="1715819231318" TEXT="muß jedweils im aktuellen Block den Rest-Speicher feststellen können"/>
|
||||
<node CREATED="1715819263910" ID="ID_1512700101" MODIFIED="1715819291686" TEXT="soll idealerweise auch noch die Destructor-Closures mit unterbringen"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1715819352242" ID="ID_1754180627" MODIFIED="1715820238650" TEXT="Implementierung">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1715820246484" ID="ID_232038748" MODIFIED="1715820255249" TEXT="Idee / Skizze">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1715819500198" ID="ID_210469417" MODIFIED="1715819513137" TEXT="ein Paar (next*, remaining_size)">
|
||||
<node CREATED="1715819811133" ID="ID_1658998228" LINK="https://en.cppreference.com/w/cpp/memory/align" MODIFIED="1715819832631" TEXT="damit kann man die std::align()-Funktion verwenden">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1715819526899" ID="ID_53500032" MODIFIED="1715819535331" TEXT="am Anfang jeden Blocks">
|
||||
<node CREATED="1715819536259" ID="ID_1810416594" MODIFIED="1715819553483" TEXT="pred* zum Vorgänger"/>
|
||||
<node CREATED="1715819554882" ID="ID_153472378" MODIFIED="1715819569288" TEXT="ein LinkedElements für die Destruktoren"/>
|
||||
</node>
|
||||
<node CREATED="1715819574814" ID="ID_1318382076" MODIFIED="1715819613401" TEXT="via next + remaining_size + Blockgröße findet man den Block-Anfang"/>
|
||||
<node CREATED="1715819629757" ID="ID_1012373659" MODIFIED="1715819639488" TEXT="damit kann man vom letzten Block aus rückwärts aufrollen"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1715820275925" ID="ID_1184193638" MODIFIED="1715820287810" TEXT="Standardfall: Speicher belegen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1715820259913" ID="ID_13842300" MODIFIED="1715820269104" TEXT="Check für zu große Objekte">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1715820289221" ID="ID_1541316374" MODIFIED="1715820300780" TEXT="Überlauf: neuen Block belegen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1715820305436" ID="ID_1741026762" MODIFIED="1715820308396" TEXT="Clean-up">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1715790315814" ID="ID_878890004" MODIFIED="1715790393998" TEXT="Lösung für die Destruktoren schaffen">
|
||||
<linktarget COLOR="#af578d" DESTINATION="ID_878890004" ENDARROW="Default" ENDINCLINATION="-446;33;" ID="Arrow_ID_464677545" SOURCE="ID_412040509" STARTARROW="None" STARTINCLINATION="-568;-24;"/>
|
||||
|
|
@ -81730,8 +81760,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
Der Beschluß zur Lösung sieht vor, diese Belange <i>markierbar </i>zu machen, um dann später differenziert handeln zu können.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1715790540241" ID="ID_698638121" MODIFIED="1715795875494" TEXT="Registry für clean-up-Aktionen direkt im Cluster verankern">
|
||||
|
|
@ -81747,8 +81776,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
...somit kann auf Basis der einzelnen, konkreten Datenstruktur entschieden (und später auch korrigiert) werden, ob ein expliziter clean-up-Aufruf notwendig ist; für die einzelne Datenstruktur dürfte das lokal jeweils klar entscheidbar sein, und ich erwarte, daß durch die Anbindung an den Allocation-Cluster diese Entscheidungsmöglichkeit auch langfristig klar dokumentiert ist — und zwar sollte das von üblichen C++ Praktiken abweichende Verhalten auch als der Spezialfall dargestellt sein (wenngleich auch erwartet wird, daß die meisten Datenstrukturen von diesem Spezialfall gebrauch machen)
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<node CREATED="1715790777543" ID="ID_953637060" MODIFIED="1715790789971" TEXT="create ⟹ Destruktor wird aufgerufen"/>
|
||||
<node CREATED="1715790790703" ID="ID_578796550" MODIFIED="1715790803259" TEXT="createDisposable ⟹ Destruktor wird nicht aufgerufen"/>
|
||||
</node>
|
||||
|
|
@ -81962,8 +81990,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
Kurzfristig erscheint das als eine naheliegende Optimierung, die einem praktisch »in den Schoß fällt« (die Implementierung wird dadurch sogar drastisch einfacher). Aber längerfristig befürchte ich eine heimtücksiche Gefahr, denn die hier genommene Abkürzung kann leicht übersehen werden, da sie den üblichen Gepflogenheiten zuwiderläuft. Im Lauf der Zeit können sich so Speicher- und Ressourcen-Lecks einschleichen, die dann nur mit erheblichem und fokussiertem Aufwand aufzuräumen sind
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1715786638937" ID="ID_220404719" MODIFIED="1715787515314" TEXT="C++ Basis-Kontrakt: Determinismus">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
|
|
@ -81975,8 +82002,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
Es handelt sich um eines der markanten Eigenschaften der Sprache C++ : Kontrolle und Determinismus bis ins kleinste Detail — und das prägt den alltäglichen Stil der Arbeit; weithin kann man sich auf Abstraktionen verlassen, weil diese sich wiederum auf Abstraktionen verlassen können; wenn alles genau und zuverlässig ist, dann werden auch weitreichende Aktionen planbar und handhabbar.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1715787292122" ID="ID_882850258" MODIFIED="1715787964678" TEXT="es ist ein weit-reichendes Subsystem">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
|
|
@ -81988,8 +82014,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
Hier geht es um das gesamte low-level-Model, sowie möglicherweise Teile des Build-Prozesses und des Regelwerks, die daran angeknüpft sein könnten — und das bedeutet, mit einer (wie es zunächst scheint) sehr lokalen und tief verborgenen Optimierung könnte der Grund-Kontrakt in einem erheblichen Teil der Applikation geändert werden
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1715786776566" ID="ID_1885525073" MODIFIED="1715786778242" TEXT="contra">
|
||||
|
|
@ -82003,8 +82028,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
Der Aufwand, der allein für das Aufrufen der aller Destruktoren getrieben werden muß, ist nicht unerheblich, denn für jeden Typ muß eine Closure im Datensegment erzeugt werden und für jede einzelne Allokation muß diese per Funktionszeiger aufrufbar sein; außerdem muß die gesamte Allokation navigierbar gemacht werden — also zwei »Slots« zusätzlich für jede einzelne Allokation. Das ist sehr viel für eine Datenstruktur, die aus vielen kleinen und sehr flexiblen Descriptor-Elementen bestehen wird; die meisten Nodes haben erwartungsgemäß nur einen Eingang und einen Ausgang, was bedeutet, daß für jeweils nur eine einzige ID (ein »Slot«) zusätzlich ein Container (2 »Slot«) und dann noch 4 »Slot« Allokations-Overhead notwendig sind.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1715786779246" ID="ID_1339652048" MODIFIED="1715788973479">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
|
|
@ -82016,8 +82040,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
in der Regel sind es<i> cold pages</i>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
|
|
@ -82027,8 +82050,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
Aus Performance-Sicht besonders fatal ist, daß zum Zeitpunkt der Bulk-de-Allokation mit hoher Wahrscheinlichkeit alle betroffenen memory pages bereits »cold« sind, d.h. aus dem Cache herausgefallen; wir müssen also eine Menge von Speicherseiten über den Bus ziehen, bloß um sie zu navigieren und dann...
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1715786817201" ID="ID_1883341443" MODIFIED="1715789112354" TEXT="90% der Fälle brauchen keinen dtor-Aufruf">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
|
|
@ -82040,8 +82062,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
...in den allermeisten Fällen nämlich<i> exakt gar nichts</i>  zu tun. Dies unter der Annahme, daß die Struktur größtenteils selbst-referentiell ist; zwar werden dadurch reihenweise verkettete Destruktor-Aufrufe stattfinden, welche aber alle letztlich beim Allocator enden, welcher dann (ganz bewußt) nichts tut, weil der gesamte Speicherblock anschließend ohnehin verworfen wird. Da es sich jedoch um dynamisch aufgebaute Datenstrukturen handelt, kann der Optimizer diesen Leerlauf nicht erkennen und beseitigen
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1715786961514" ID="ID_1214786701" MODIFIED="1715789369565" TEXT="es handelt sich um einer permanent-laufende Aktivität">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
|
|
@ -82053,8 +82074,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
Es steht zu befürchten, daß während der normalen Edit-Tätigkeit alle par 1/10-sec ein Builder-Lauf getriggert wird — und ich schätze, daß ein erheblicher Anteil der tatsächlichen Laufzeit in das Konstruieren der Datenstruktur geht, denn der zugrundeliegende trade-off ist ja grade<i>  space-for-time.</i> Wenngleich auch der Neubau ebenfalls schlecht für den Cache ist, so kann man doch zumindet in Teilen hoffen, daß die neu gebauten Strukturen zumindest bis zur ersten Berührung durch den Play-Prozeß im L3 bleiben. Für die alten Strukturen gilt das aber nicht, sie stellen rein nutzlosen Balast dar.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1715789372444" ID="ID_869337683" MODIFIED="1715789375047" TEXT="Diskussion">
|
||||
|
|
@ -82071,8 +82091,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
Ich handle hier nur auf Basis eines Bauchgefühls, und alle Erfahrung zeigt, daß man dabei meist die Gewichte falsch setzt.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node CREATED="1715789557219" ID="ID_1705458605" MODIFIED="1715789587814" TEXT="ein Aufweichen des Determinismus-Prinzips ist später nicht mehr korrigierbar">
|
||||
|
|
@ -82094,8 +82113,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
Angenommen, ich mache diese Optimierung jetzt <b>nicht</b>, bereite sie aber vor; später dann zeigt sich (mit guter Wahrscheinlichkeit) tatsächlich ein relevanter Overhead ⟹ dann ist der Druck zur Optimierung umso stärker, und man wird die vorbereitete Option »ziehen« und die weitreichenden Konsequenzen in Kauf nehmen, da die Behebung eines konkreten Problems immer alle strategischen und methodischen Erwägungen <b>übersteuert</b>. Das wäre der schlechtest mögliche Verlauf, denn zu eine so späten Zeitpunkt kann man kaum mehr etwas tun, um eine weitreichende Änderung der Konventionen abzufedern
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue