BufferProvider: implement heuristic to trigger pool clean-up

This commit is contained in:
Fischlurch 2026-05-25 20:24:25 +02:00
parent 08fef0c64c
commit 5a7cfb613f
3 changed files with 255 additions and 13 deletions

View file

@ -100,6 +100,7 @@ namespace mem {
using std::move; using std::move;
using std::forward; using std::forward;
using std::invocable; using std::invocable;
using util::max;
using util::unConst; using util::unConst;
using util::isLimited; using util::isLimited;
using std::this_thread::sleep_for; using std::this_thread::sleep_for;
@ -147,6 +148,7 @@ namespace mem {
BlockList blocks_; BlockList blocks_;
int32_t maxScore_{1}; int32_t maxScore_{1};
int32_t turnover_{0};
std::function<void(LocalMemPool&)> shutdownHook_{}; std::function<void(LocalMemPool&)> shutdownHook_{};
@ -201,6 +203,13 @@ namespace mem {
return bool(anyFree (sizRequest)); return bool(anyFree (sizRequest));
} }
/** turnover-based trigger for heuristic pool clean-up */
bool
shouldCleanup (float sharpen =1.0f) const
{
return turnover_ * float(MATCH_SCORE) <= maxScore_ * sharpen;
}
/** /**
* Determine to what extent the indicated allocation request * Determine to what extent the indicated allocation request
* could be handled, given the current memory available in the pool. * could be handled, given the current memory available in the pool.
@ -252,6 +261,8 @@ namespace mem {
{ {
Alloc alloc{mem,siz}; Alloc alloc{mem,siz};
AllocReceiver::supply (alloc); AllocReceiver::supply (alloc);
if (alloc.mem)
++turnover_;
} }
/** /**
@ -264,7 +275,10 @@ namespace mem {
supplyImmediately (Alloc alloc) supplyImmediately (Alloc alloc)
{ {
if (alloc.mem) if (alloc.mem)
{
blocks_.emplace_front (move(alloc)); blocks_.emplace_front (move(alloc));
++turnover_;
}
// otherwise: allocation not serviced, do not add anything // otherwise: allocation not serviced, do not add anything
} }
@ -285,6 +299,7 @@ namespace mem {
throw err::Logic{"returning known allocation that is not marked as used"}; throw err::Logic{"returning known allocation that is not marked as used"};
block->used = false; block->used = false;
ENSURE (not block->resd); ENSURE (not block->resd);
--turnover_;
} }
/** /**
@ -325,7 +340,11 @@ namespace mem {
yield (uint cnt, size_t siz, FUN&& consumer) yield (uint cnt, size_t siz, FUN&& consumer)
{ {
ingest(); ingest();
if (blocks_.empty())
return 0;
uint remain{0};
uint removed{0}; uint removed{0};
int32_t newMax{0};
for (auto pos = blocks_.begin() for (auto pos = blocks_.begin()
; pos != blocks_.end() ; pos != blocks_.end()
; ) ; )
@ -341,8 +360,16 @@ namespace mem {
--cnt; --cnt;
} }
else else
{
newMax = max (newMax, pos->score);
++remain;
++pos; ++pos;
}
// recalibrate proportionally
uint prevSiz{removed+remain};
ENSURE (0 < prevSiz);
turnover_ *= float(remain)/prevSiz;
maxScore_ = max (newMax,1);
return removed; return removed;
} }
@ -359,6 +386,7 @@ namespace mem {
cleanup (double degree, FUN&& consumer) cleanup (double degree, FUN&& consumer)
{ {
ingest(); ingest();
uint remain{0};
uint removed{0}; uint removed{0};
int32_t killLevel = degree * maxScore_; int32_t killLevel = degree * maxScore_;
for (auto pos = blocks_.begin() for (auto pos = blocks_.begin()
@ -373,12 +401,14 @@ namespace mem {
} }
else else
{ {
++remain;
pos->score -= killLevel; pos->score -= killLevel;
++pos; ++pos;
} }
// recalibrate all score levels // recalibrate all score levels
maxScore_ -= killLevel; maxScore_ -= killLevel;
maxScore_ = util::max (maxScore_, 1); maxScore_ = max (maxScore_, 1);
turnover_ = remain;
return removed; return removed;
} }
@ -545,6 +575,18 @@ namespace mem {
REQUIRE (entry, "Test refers to entry unknown in pool"); REQUIRE (entry, "Test refers to entry unknown in pool");
return entry->score; return entry->score;
} }
int32_t
getMaxScore()
{
return memPool_.maxScore_;
}
int32_t
getTurnover()
{
return memPool_.turnover_;
}
}; };

View file

@ -379,36 +379,205 @@ namespace test {
SHOW_EXPR(show(globalPool)); SHOW_EXPR(show(globalPool));
SHOW_EXPR(watch(pool).size()) SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
supply(3); supply(3);
SHOW_EXPR("supply")
SHOW_EXPR(show(globalPool)); SHOW_EXPR(show(globalPool));
SHOW_EXPR(watch(pool).size()) SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).cntFree()) SHOW_EXPR(watch(pool).cntFree())
reserve(2); reserve(2);
SHOW_EXPR("reserve")
SHOW_EXPR(watch(pool).size()) SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).cntFree()) SHOW_EXPR(watch(pool).cntFree())
SHOW_EXPR(watch(pool).cntResd()) SHOW_EXPR(watch(pool).cntResd())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
claim(3); claim(3);
SHOW_EXPR("claim")
SHOW_EXPR(watch(pool).size()) SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).cntFree()) SHOW_EXPR(watch(pool).cntFree())
SHOW_EXPR(watch(pool).cntResd()) SHOW_EXPR(watch(pool).cntResd())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
SHOW_EXPR(show(usedBuff)); SHOW_EXPR(show(usedBuff));
free(3); free(3);
SHOW_EXPR("free")
SHOW_EXPR(watch(pool).size()) SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).cntFree()) SHOW_EXPR(watch(pool).cntFree())
SHOW_EXPR(watch(pool).cntResd()) SHOW_EXPR(watch(pool).cntResd())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
SHOW_EXPR(show(usedBuff)); SHOW_EXPR(show(usedBuff));
pool.yield (3, SIZ, pushMem); SHOW_EXPR(pool.shouldCleanup())
uint removed = pool.cleanup(0.5, pushMem);
SHOW_EXPR(removed)
SHOW_EXPR(watch(pool).size()) SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
SHOW_EXPR(show(globalPool));
claim(1);
SHOW_EXPR("claim")
SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).cntFree())
SHOW_EXPR(watch(pool).cntResd())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
free(1);
SHOW_EXPR("free")
SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).cntFree())
SHOW_EXPR(watch(pool).cntResd())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
SHOW_EXPR(pool.shouldCleanup())
claim(1);
SHOW_EXPR("claim")
SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).cntFree())
SHOW_EXPR(watch(pool).cntResd())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
free(1);
SHOW_EXPR("free")
SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).cntFree())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
SHOW_EXPR(pool.shouldCleanup())
removed = pool.cleanup(0.5, pushMem);
SHOW_EXPR(removed)
SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
SHOW_EXPR(show(globalPool));
supply(4);
SHOW_EXPR("supply")
SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
SHOW_EXPR(show(globalPool));
claim(3);
SHOW_EXPR("claim")
SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).cntFree())
SHOW_EXPR(watch(pool).cntResd())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
free(2);
SHOW_EXPR("free")
SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).cntFree())
SHOW_EXPR(watch(pool).cntResd())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
SHOW_EXPR(pool.shouldCleanup())
claim(2);
SHOW_EXPR("claim")
SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).cntFree())
SHOW_EXPR(watch(pool).cntResd())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
supply(4);
SHOW_EXPR("supply")
SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
SHOW_EXPR(show(globalPool));
free(2);
SHOW_EXPR("free")
SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).cntFree())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
SHOW_EXPR(show(usedBuff));
claim(1);
SHOW_EXPR("claim")
SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).cntFree())
SHOW_EXPR(watch(pool).cntResd())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
free(1);
SHOW_EXPR("free")
SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).cntFree())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
SHOW_EXPR(show(usedBuff));
SHOW_EXPR(pool.shouldCleanup())
removed = pool.cleanup(0.5, pushMem);
SHOW_EXPR(removed)
SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
SHOW_EXPR(show(globalPool));
claim(1);
SHOW_EXPR("claim")
SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).cntFree())
SHOW_EXPR(watch(pool).cntResd())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
free(2);
SHOW_EXPR("free")
SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).cntFree())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
SHOW_EXPR(pool.shouldCleanup())
removed = pool.cleanup(0.5, pushMem);
SHOW_EXPR(removed)
SHOW_EXPR(watch(pool).size())
SHOW_EXPR(watch(pool).getMaxScore())
SHOW_EXPR(watch(pool).getTurnover())
SHOW_EXPR(show(globalPool)); SHOW_EXPR(show(globalPool));
} }

View file

@ -145434,8 +145434,8 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
</body> </body>
</html></richcontent> </html></richcontent>
</node> </node>
<node CREATED="1778947001639" ID="ID_78533321" MODIFIED="1779665464192" TEXT="Idee: &#xbb;turnover&#xab; &#x2014; jedem Block eine Chance geben"> <node CREATED="1778947001639" ID="ID_78533321" MODIFIED="1779724531120" TEXT="Idee: &#xbb;turnover&#xab; &#x2014; jedem Block eine Chance geben">
<linktarget COLOR="#4f65bc" DESTINATION="ID_78533321" ENDARROW="Default" ENDINCLINATION="-548;697;" ID="Arrow_ID_1519732497" SOURCE="ID_1461846299" STARTARROW="Default" STARTINCLINATION="286;13;"/> <linktarget COLOR="#4f65bc" DESTINATION="ID_78533321" ENDARROW="Default" ENDINCLINATION="-548;697;" ID="Arrow_ID_1519732497" SOURCE="ID_1461846299" STARTARROW="Default" STARTINCLINATION="345;16;"/>
<icon BUILTIN="forward"/> <icon BUILTIN="forward"/>
<node CREATED="1778947114570" ID="ID_914679223" MODIFIED="1778947126240" TEXT="ankommende Bl&#xf6;cke erh&#xf6;hen den Turnover"/> <node CREATED="1778947114570" ID="ID_914679223" MODIFIED="1778947126240" TEXT="ankommende Bl&#xf6;cke erh&#xf6;hen den Turnover"/>
<node CREATED="1778947127539" ID="ID_253931638" MODIFIED="1778947136630" TEXT="jede de-Allokation veringert den Turnover"/> <node CREATED="1778947127539" ID="ID_253931638" MODIFIED="1778947136630" TEXT="jede de-Allokation veringert den Turnover"/>
@ -145469,7 +145469,7 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
</body> </body>
</html></richcontent> </html></richcontent>
</node> </node>
<node CREATED="1778948068575" ID="ID_855345858" MODIFIED="1778948159062" TEXT="verwende also MaxScore / MATCH_SCORE als Triggerschwelle gegen den Turnout"/> <node CREATED="1778948068575" ID="ID_855345858" MODIFIED="1779725685738" TEXT="verwende also MaxScore / MATCH_SCORE als Triggerschwelle gegen den Turnover"/>
<node CREATED="1778948224807" ID="ID_1282800052" MODIFIED="1778948275175" TEXT="zus&#xe4;tzlicher Gewichtsfaktor um die Sch&#xe4;rfe der &#xdc;berpr&#xfc;fung zu regulieren"/> <node CREATED="1778948224807" ID="ID_1282800052" MODIFIED="1778948275175" TEXT="zus&#xe4;tzlicher Gewichtsfaktor um die Sch&#xe4;rfe der &#xdc;berpr&#xfc;fung zu regulieren"/>
</node> </node>
</node> </node>
@ -146874,14 +146874,33 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
<node CREATED="1777164514849" ID="ID_489761092" MODIFIED="1777164525297" TEXT="und gew&#xe4;hlt wird nach maximalem selectionScore"/> <node CREATED="1777164514849" ID="ID_489761092" MODIFIED="1777164525297" TEXT="und gew&#xe4;hlt wird nach maximalem selectionScore"/>
<node CREATED="1777164528024" ID="ID_1047876896" MODIFIED="1777164541639" TEXT="dieser gew&#xe4;hlte Buffer bekommt dann einen Score-Update"/> <node CREATED="1777164528024" ID="ID_1047876896" MODIFIED="1777164541639" TEXT="dieser gew&#xe4;hlte Buffer bekommt dann einen Score-Update"/>
</node> </node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1779664650625" ID="ID_1141255727" MODIFIED="1779664857110" TEXT="Dazu einen 2.Layer &#x27f9; Heuristik zum Triggern"> <node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1779664650625" ID="ID_1141255727" MODIFIED="1779729238478" TEXT="Dazu einen 2.Layer &#x27f9; Heuristik zum Triggern">
<linktarget COLOR="#4d5f6c" DESTINATION="ID_1141255727" ENDARROW="Default" ENDINCLINATION="-376;22;" ID="Arrow_ID_514664149" SOURCE="ID_1129342480" STARTARROW="None" STARTINCLINATION="-76;-210;"/> <linktarget COLOR="#4d5f6c" DESTINATION="ID_1141255727" ENDARROW="Default" ENDINCLINATION="-376;22;" ID="Arrow_ID_514664149" SOURCE="ID_1129342480" STARTARROW="None" STARTINCLINATION="-76;-210;"/>
<icon BUILTIN="flag-yellow"/> <icon BUILTIN="pencil"/>
<node CREATED="1779664722365" ID="ID_1461846299" MODIFIED="1779665464192" TEXT="im Kontext vom LocalBufferStore : erweiterte Heuristik skizziert"> <node CREATED="1779664722365" ID="ID_1461846299" MODIFIED="1779724531120" TEXT="im Kontext vom LocalBufferStore : erweiterte Heuristik skizziert">
<arrowlink COLOR="#4f65bc" DESTINATION="ID_78533321" ENDARROW="Default" ENDINCLINATION="-548;697;" ID="Arrow_ID_1519732497" STARTARROW="Default" STARTINCLINATION="286;13;"/> <arrowlink COLOR="#4f65bc" DESTINATION="ID_78533321" ENDARROW="Default" ENDINCLINATION="-548;697;" ID="Arrow_ID_1519732497" STARTARROW="Default" STARTINCLINATION="345;16;"/>
<font NAME="SansSerif" SIZE="12"/> <font NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="idea"/> <icon BUILTIN="idea"/>
</node> </node>
<node COLOR="#338800" CREATED="1779678327953" ID="ID_1985264283" MODIFIED="1779724920127" TEXT="turnover-Variable einf&#xfc;hren">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1779678344575" ID="ID_1954145577" MODIFIED="1779726996289" TEXT="turnover mit aktualisieren">
<icon BUILTIN="button_ok"/>
<node CREATED="1779678355221" ID="ID_877262822" MODIFIED="1779678368820" TEXT="beim supply (neue Allokation bereitstellen)"/>
<node CREATED="1779678382051" ID="ID_466975997" MODIFIED="1779678394545" TEXT="beim retrieve (Allokation verwenden)"/>
<node CREATED="1779678403727" ID="ID_838943223" MODIFIED="1779678413410" TEXT="beim reSupply (Allokation zur&#xfc;ckgeben)"/>
<node COLOR="#338800" CREATED="1779678418733" ID="ID_763664892" MODIFIED="1779729233065" TEXT="re-Initialisieren nach clean-Up">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node COLOR="#338800" CREATED="1779678431787" ID="ID_1226724466" MODIFIED="1779733305968" TEXT="Accessor: Trigger-Status abfragen">
<icon BUILTIN="button_ok"/>
<node CREATED="1779678456264" ID="ID_1362166348" MODIFIED="1779678461993" TEXT="das ist eine pure function">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1779678463307" ID="ID_542497413" MODIFIED="1779678482680" TEXT="&quot;w&#xe4;re aktuell ein heuristisches clean-up gerechtfertigt?&quot;"/>
</node>
</node> </node>
</node> </node>
<node COLOR="#338800" CREATED="1777206625753" ID="ID_1782953860" MODIFIED="1777245252573" TEXT="Vor-Reservierung implementieren"> <node COLOR="#338800" CREATED="1777206625753" ID="ID_1782953860" MODIFIED="1777245252573" TEXT="Vor-Reservierung implementieren">
@ -147007,8 +147026,20 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
<icon BUILTIN="button_ok"/> <icon BUILTIN="button_ok"/>
</node> </node>
</node> </node>
<node COLOR="#435e98" CREATED="1779678269323" ID="ID_1821389812" MODIFIED="1779733357622" TEXT="Szenario-1">
<node CREATED="1779678286438" ID="ID_1816083165" MODIFIED="1779678297036" TEXT="3 gleichzeitig allozieren"/>
</node>
<node COLOR="#435e98" CREATED="1779733314454" ID="ID_284062895" MODIFIED="1779733357623" TEXT="Szenario-2">
<node CREATED="1779733320086" ID="ID_1528731299" MODIFIED="1779733324664" TEXT="nur einen verwenden"/>
</node>
<node COLOR="#435e98" CREATED="1779733330072" ID="ID_582928434" MODIFIED="1779733357623" TEXT="Szenario-3">
<node CREATED="1779733339598" ID="ID_1362814231" MODIFIED="1779733343707" TEXT="zwischendurch nachf&#xfc;llen"/>
<node CREATED="1779733348313" ID="ID_1867741071" MODIFIED="1779733353992" TEXT="wechselnd partiell verwenden"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1778979252922" ID="ID_155080806" MODIFIED="1779733388847" TEXT="Verhalten sollte deterministisch sein und Erwartung entsprechen">
<icon BUILTIN="pencil"/>
</node> </node>
<node CREATED="1778979252922" ID="ID_155080806" MODIFIED="1778979264429" TEXT="Verhalten sollte deterministisch vorhersagbar sein"/>
</node> </node>
</node> </node>
</node> </node>