Block-Flow: compute exponential moving average
..as a heuristic to regulate optimal Epoch duration; when Epochs are discarded, the effective fill factor can be used to guess an Epoch duration time, which would (in hindsight) lead to perfect usage of storage space
This commit is contained in:
parent
bd353d768a
commit
9d040dc49c
3 changed files with 56 additions and 22 deletions
|
|
@ -98,6 +98,7 @@ namespace gear {
|
|||
using util::Rat;
|
||||
using util::isnil;
|
||||
using lib::time::Time;
|
||||
using lib::time::FSecs;
|
||||
using lib::time::TimeVar;
|
||||
using lib::time::Duration;
|
||||
using lib::time::FrameRate;
|
||||
|
|
@ -436,13 +437,21 @@ namespace gear {
|
|||
* actual Epoch duration by the fill factor (longer Epoch => less capacity).
|
||||
* To avoid control oscillations however, it seems prudent to use damping by
|
||||
* an exponential moving average, nominally over #AVERAGE_EPOCHS.
|
||||
* The current epochStep_ is assumed to be such a moving average, and will be
|
||||
* updated accordingly.
|
||||
* The current epochStep_ is assumed to be such a moving average,
|
||||
* and will be updated accordingly.
|
||||
* @todo the unclear status of the time base type hampers calculation
|
||||
* with fractional time values, as is necessary here. As workaround,
|
||||
* the argument is typed as TimeVar, which opens a calculation path
|
||||
* without much spurious range checks. /////////////////////////////////////////////////////////TICKET #1259 : reorganise raw time base datatypes : need conversion path into FSecs
|
||||
*/
|
||||
void
|
||||
markEpochUnderflow (Duration actualLen, Rat fillFactor)
|
||||
markEpochUnderflow (TimeVar actualLen, Rat fillFactor)
|
||||
{
|
||||
UNIMPLEMENTED ("adjust size when detecting partially filled Epochs");
|
||||
Rat contribution = Rat{_raw(actualLen), _raw(epochStep_)} / fillFactor;
|
||||
// Exponential MA: mean ≔ mean * (N-1)/N + newVal/N
|
||||
const Rat N = AVERAGE_EPOCHS;
|
||||
Rat avgFactor = (contribution + N-1) / N;
|
||||
adjustEpochStep (avgFactor);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -270,7 +270,9 @@ namespace test {
|
|||
CHECK (watch(bFlow).allEpochs() == "10s200ms|10s400ms|10s600ms|10s800ms|11s|11s131ms|11s262ms|11s393ms|11s524ms"_expect);
|
||||
CHECK (watch(bFlow).find(a7) == "11s524ms"_expect);
|
||||
|
||||
SHOW_EXPR(bFlow.getEpochStep())
|
||||
bFlow.discardBefore (Time{999,10});
|
||||
SHOW_EXPR(bFlow.getEpochStep())
|
||||
CHECK (watch(bFlow).allEpochs() == "11s|11s131ms|11s262ms|11s393ms|11s524ms"_expect);
|
||||
|
||||
// placed into the oldest Epoch still alive
|
||||
|
|
@ -280,7 +282,10 @@ namespace test {
|
|||
|
||||
|
||||
|
||||
/** @test TODO load based regulation of Epoch spacing
|
||||
/** @test load based regulation of Epoch spacing
|
||||
* - on overflow, capacity is boosted by a fixed factor
|
||||
* - on clean-up, a moving average of (in hindsight) optimal length is
|
||||
* computed and used as the new Epoch spacing
|
||||
* @todo WIP 7/23 ⟶ ✔define ⟶ 🔁implement
|
||||
*/
|
||||
void
|
||||
|
|
@ -289,27 +294,32 @@ namespace test {
|
|||
BlockFlow bFlow;
|
||||
CHECK (bFlow.getEpochStep() == INITIAL_EPOCH_STEP);
|
||||
|
||||
// whenever an Epoch overflow happens, capacity is boosted by reducing the Epoch duration
|
||||
bFlow.markEpochOverflow();
|
||||
CHECK (bFlow.getEpochStep() == INITIAL_EPOCH_STEP * OVERFLOW_BOOST_FACTOR);
|
||||
bFlow.markEpochOverflow();
|
||||
CHECK (bFlow.getEpochStep() == INITIAL_EPOCH_STEP * OVERFLOW_BOOST_FACTOR*OVERFLOW_BOOST_FACTOR);
|
||||
|
||||
Duration dur1 = INITIAL_EPOCH_STEP;
|
||||
Duration dur2 = INITIAL_EPOCH_STEP * OVERFLOW_BOOST_FACTOR;
|
||||
// To counteract this increase, on clean-up the actual fill rate of the Extent
|
||||
// serves to guess an optimal Epoch duration, which is averaged exponentially
|
||||
|
||||
// Using just arbitrary demo values for some fictional Epochs
|
||||
TimeVar dur1 = INITIAL_EPOCH_STEP;
|
||||
Rat fill1 = 8_r/10;
|
||||
TimeVar dur2 = INITIAL_EPOCH_STEP * OVERFLOW_BOOST_FACTOR;
|
||||
Rat fill2 = 3_r/10;
|
||||
|
||||
TimeVar step = bFlow.getEpochStep();
|
||||
Rat fill = 8_r/10;
|
||||
Rat N = AVERAGE_EPOCHS;
|
||||
TimeVar step = bFlow.getEpochStep();
|
||||
|
||||
bFlow.markEpochUnderflow (dur1, fill);
|
||||
CHECK (bFlow.getEpochStep() == step*((N-1)/N) + dur1*(1/N /fill));
|
||||
bFlow.markEpochUnderflow (dur1, fill1);
|
||||
CHECK (bFlow.getEpochStep() == Duration{FSecs{step}*(N-1)/N + FSecs{dur1}/fill1/N});
|
||||
|
||||
step = bFlow.getEpochStep();
|
||||
fill = 3_r/10;
|
||||
bFlow.markEpochUnderflow (dur2, fill);
|
||||
CHECK (bFlow.getEpochStep() == step*((N-1)/N) + dur2*(1/N /fill));
|
||||
}
|
||||
|
||||
bFlow.markEpochUnderflow (dur2, fill2);
|
||||
CHECK (bFlow.getEpochStep() == Duration{FSecs{step}*(N-1)/N + FSecs{dur2}/fill2/N});
|
||||
} // Note: for verification the exponential average is computed via FSecs
|
||||
// which is a different calculation path but yields the same result
|
||||
|
||||
|
||||
/** @test TODO maintain progression of epochs.
|
||||
|
|
|
|||
|
|
@ -79747,8 +79747,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
Entscheidung: Allokation entgleist nur<i> ausnahmsweise</i>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<arrowlink COLOR="#fd1a6e" DESTINATION="ID_1315709817" ENDARROW="Default" ENDINCLINATION="21;-31;" ID="Arrow_ID_1483237280" STARTARROW="None" STARTINCLINATION="-248;12;"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
|
|
@ -80161,15 +80160,17 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1689204305717" ID="ID_123055064" MODIFIED="1689204325821" TEXT="später wird auch dieses Thema auf TimingObservable aufsetzen">
|
||||
<linktarget COLOR="#8d8fd3" DESTINATION="ID_123055064" ENDARROW="Default" ENDINCLINATION="606;0;" ID="Arrow_ID_1147910894" SOURCE="ID_900092388" STARTARROW="None" STARTINCLINATION="216;0;"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1689204331764" ID="ID_578018270" MODIFIED="1689204425304" TEXT="vorerst einfache gedämpfte Mittelung">
|
||||
<node COLOR="#435e98" CREATED="1689204331764" ID="ID_578018270" MODIFIED="1689555121736" TEXT="vorerst einfache gedämpfte Mittelung">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1689354964927" ID="ID_1525931195" MODIFIED="1689354982888" TEXT="mir schwebt ein exponentielles moving-average vor"/>
|
||||
<node CREATED="1689355051116" ID="ID_214862798" MODIFIED="1689355076675" TEXT="Ansatz">
|
||||
<node CREATED="1689355077335" ID="ID_250434643" MODIFIED="1689355094729" TEXT="lineares moving-average: den N-ten alten Wert subtrahieren"/>
|
||||
<node CREATED="1689355095725" ID="ID_917795868" MODIFIED="1689356305847" TEXT="exponentielles moving-average: ein N-tel vom gemittelten Wert subtrahieren">
|
||||
<linktarget COLOR="#579ad8" DESTINATION="ID_917795868" ENDARROW="Default" ENDINCLINATION="-206;8;" ID="Arrow_ID_1287643203" SOURCE="ID_367226311" STARTARROW="None" STARTINCLINATION="292;0;"/>
|
||||
<node COLOR="#338800" CREATED="1689355095725" ID="ID_917795868" MODIFIED="1689555145374" TEXT="exponentielles moving-average: ein N-tel vom gemittelten Wert subtrahieren">
|
||||
<linktarget COLOR="#579ad8" DESTINATION="ID_917795868" ENDARROW="Default" ENDINCLINATION="-209;8;" ID="Arrow_ID_1287643203" SOURCE="ID_367226311" STARTARROW="None" STARTINCLINATION="292;0;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1689355137015" ID="ID_864577627" MODIFIED="1689355148010" TEXT="Konsequenz...">
|
||||
|
|
@ -80202,6 +80203,11 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<node COLOR="#435e98" CREATED="1689555157106" ID="ID_758511598" MODIFIED="1689555196669" TEXT="zunächst überniimmt INITIAL_EPOCH_STEP diese Rolle"/>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1689555181934" ID="ID_900092388" MODIFIED="1689555228891" TEXT="später ein persistentes TimingObservable">
|
||||
<arrowlink COLOR="#8d8fd3" DESTINATION="ID_123055064" ENDARROW="Default" ENDINCLINATION="606;0;" ID="Arrow_ID_1147910894" STARTARROW="None" STARTINCLINATION="216;0;"/>
|
||||
<icon BUILTIN="hourglass"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -80229,12 +80235,21 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1689356233875" ID="ID_1117159632" MODIFIED="1689356241731" TEXT="das wirkt mit einer gewissen Verzögerung"/>
|
||||
<node CREATED="1689356263015" ID="ID_367226311" MODIFIED="1689356314144" TEXT="hier wird exponential-MA angewendet">
|
||||
<arrowlink COLOR="#579ad8" DESTINATION="ID_917795868" ENDARROW="Default" ENDINCLINATION="-206;8;" ID="Arrow_ID_1287643203" STARTARROW="None" STARTINCLINATION="292;0;"/>
|
||||
<arrowlink COLOR="#579ad8" DESTINATION="ID_917795868" ENDARROW="Default" ENDINCLINATION="-209;8;" ID="Arrow_ID_1287643203" STARTARROW="None" STARTINCLINATION="292;0;"/>
|
||||
</node>
|
||||
<node CREATED="1689356572198" ID="ID_1540220100" MODIFIED="1689356660985" TEXT="»Sollwert« ⟹ als Signal einspeisen">
|
||||
<node CREATED="1689356669065" ID="ID_492493887" MODIFIED="1689356705152" TEXT="»Sollwert« ≡ die Epochen-Länge, die genügt hätte"/>
|
||||
<node CREATED="1689356713555" ID="ID_1631540322" MODIFIED="1689356790172" TEXT="angenommen die Deadlines sind gleichverteilt ⟹ direkt den Füllstand nehmen"/>
|
||||
<node CREATED="1689356905327" ID="ID_1889066607" MODIFIED="1689357557781" TEXT="⟹ aktuelle Länge / Füllstand-Faktor"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1689555058905" ID="ID_241155664" MODIFIED="1689555109664" TEXT="Problem: aktuelle Länge ermitteln">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1689555238439" ID="ID_1830307338" MODIFIED="1689555250023" TEXT="wir speichern nur die Deadline">
|
||||
<icon BUILTIN="info"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1689555251273" ID="ID_860911583" MODIFIED="1689555283933" TEXT="für die erste Epoche ist der Anfangspunkt nicht bekannt">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1689356940427" ID="ID_1868278031" MODIFIED="1689356956670" TEXT="damit regelt dieser Mechanismus stets herunter"/>
|
||||
<node CREATED="1689357043350" ID="ID_1771390424" MODIFIED="1689357058027" TEXT="aber langsamer, da er nur im Tick läuft"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue