Scheduler-test: document and verify weight adapted timing

The helper developed thus far produces a sequence of
weight factors per level, which could then be multiplied
with an actual delay base time to produce a concrete schedule.

These calculations, while simple, are difficult to understand;
recommended to use the values tabulated in this test together
with a `graphviz` rendering of the node graph (🠲 `printTopologyDOT()`)
This commit is contained in:
Fischlurch 2023-12-31 21:59:16 +01:00
parent e9e7d954b1
commit 55cb028abf
4 changed files with 254 additions and 43 deletions

View file

@ -29,6 +29,7 @@
#include "test-chain-load.hpp"
#include "vault/gear/scheduler.hpp"
#include "lib/time/timevalue.hpp"
#include "lib/format-string.hpp"
#include "lib/format-cout.hpp"
#include "lib/test/diagnostic-output.hpp"//////////////////////////TODO work in distress
//#include "lib/format-string.hpp"
@ -50,6 +51,7 @@ namespace test {
// using lib::time::FrameRate;
// using lib::time::Offset;
// using lib::time::Time;
using util::_Fmt;
namespace { // Test definitions and setup...
@ -161,53 +163,114 @@ SHOW_EXPR(micros);
CHECK (micros < 550);
CHECK (micros > 450);
std::vector<LevelWeight> levelWeights = testLoad.allLevelWeights().effuse();
std::vector<double> scheduleSeq = testLoad.levelScheduleSequence(4).effuse();
SHOW_EXPR(levelWeights.size())
for (uint i=0; i<levelWeights.size(); ++i)
{
cout<<"level:"<<i<<" nodes:"<<levelWeights[i].nodes<<" ∑="<<levelWeights[i].weight<<" ..step="<<scheduleSeq[i]<<endl;
}
auto node = testLoad.allNodePtr().effuse();
auto level = testLoad.allLevelWeights().effuse();
CHECK (level.size() == 27);
auto node = testLoad.allNodePtr().effuse();
for (auto& n : node)
cout<<"level:"<<n->level<<" w="<<n->weight;
auto getWeight = [&](uint level) { return levelWeights[level].weight; };
CHECK (node[22]->level == 16);
CHECK (node[23]->level == 17); CHECK (node[23]->weight == 3); CHECK (getWeight(17) == 3);
_Fmt nodeFmt{"i=%-2d lev:%-2d w=%1d"};
_Fmt levelFmt{" Σ%-2d Σw:%2d"};
auto nodeStr = [&](uint i)
{
size_t l = node[i]->level;
return string{nodeFmt % i % node[i]->level % node[i]->weight}
+ (i == level[l].endidx? string{levelFmt % level[l].nodes % level[l].weight}
: string{" · · "});
};
// |idx--level--wght|-levelSum-------
CHECK (nodeStr( 1) == "i=1 lev:1 w=0 Σ1 Σw: 0"_expect);
CHECK (nodeStr( 2) == "i=2 lev:2 w=2 Σ1 Σw: 2"_expect);
CHECK (nodeStr( 3) == "i=3 lev:3 w=0 Σ1 Σw: 0"_expect);
CHECK (nodeStr( 4) == "i=4 lev:4 w=0 Σ1 Σw: 0"_expect);
CHECK (nodeStr( 5) == "i=5 lev:5 w=0 Σ1 Σw: 0"_expect);
CHECK (nodeStr( 6) == "i=6 lev:6 w=1 Σ1 Σw: 1"_expect);
CHECK (nodeStr( 7) == "i=7 lev:7 w=2 Σ1 Σw: 2"_expect);
CHECK (nodeStr( 8) == "i=8 lev:8 w=2 Σ1 Σw: 2"_expect);
CHECK (nodeStr( 9) == "i=9 lev:9 w=1 · · "_expect);
CHECK (nodeStr(10) == "i=10 lev:9 w=1 Σ2 Σw: 2"_expect);
CHECK (nodeStr(11) == "i=11 lev:10 w=0 · · "_expect);
CHECK (nodeStr(12) == "i=12 lev:10 w=0 Σ2 Σw: 0"_expect);
CHECK (nodeStr(13) == "i=13 lev:11 w=0 · · "_expect);
CHECK (nodeStr(14) == "i=14 lev:11 w=0 Σ2 Σw: 0"_expect);
CHECK (nodeStr(15) == "i=15 lev:12 w=1 · · "_expect);
CHECK (nodeStr(16) == "i=16 lev:12 w=1 Σ2 Σw: 2"_expect);
CHECK (nodeStr(17) == "i=17 lev:13 w=1 · · "_expect);
CHECK (nodeStr(18) == "i=18 lev:13 w=1 Σ2 Σw: 2"_expect);
CHECK (nodeStr(19) == "i=19 lev:14 w=2 · · "_expect);
CHECK (nodeStr(20) == "i=20 lev:14 w=2 Σ2 Σw: 4"_expect);
CHECK (nodeStr(21) == "i=21 lev:15 w=0 Σ1 Σw: 0"_expect);
CHECK (nodeStr(22) == "i=22 lev:16 w=1 Σ1 Σw: 1"_expect);
CHECK (nodeStr(23) == "i=23 lev:17 w=3 Σ1 Σw: 3"_expect);
CHECK (nodeStr(24) == "i=24 lev:18 w=0 · · "_expect);
CHECK (nodeStr(25) == "i=25 lev:18 w=0 · · "_expect);
CHECK (nodeStr(26) == "i=26 lev:18 w=0 · · "_expect);
CHECK (nodeStr(27) == "i=27 lev:18 w=0 · · "_expect);
CHECK (nodeStr(28) == "i=28 lev:18 w=0 Σ5 Σw: 0"_expect);
CHECK (nodeStr(29) == "i=29 lev:19 w=2 · · "_expect);
CHECK (nodeStr(30) == "i=30 lev:19 w=2 · · "_expect);
CHECK (nodeStr(31) == "i=31 lev:19 w=2 · · "_expect);
CHECK (nodeStr(32) == "i=32 lev:19 w=2 · · "_expect);
CHECK (nodeStr(33) == "i=33 lev:19 w=2 Σ5 Σw:10"_expect);
CHECK (nodeStr(34) == "i=34 lev:20 w=3 · · "_expect);
CHECK (nodeStr(35) == "i=35 lev:20 w=2 Σ2 Σw: 5"_expect);
CHECK (nodeStr(36) == "i=36 lev:21 w=1 · · "_expect);
CHECK (nodeStr(37) == "i=37 lev:21 w=1 · · "_expect);
CHECK (nodeStr(38) == "i=38 lev:21 w=3 Σ3 Σw: 5"_expect);
CHECK (nodeStr(39) == "i=39 lev:22 w=3 · · "_expect);
CHECK (nodeStr(40) == "i=40 lev:22 w=3 · · "_expect);
CHECK (nodeStr(41) == "i=41 lev:22 w=0 · · "_expect);
CHECK (nodeStr(42) == "i=42 lev:22 w=0 · · "_expect);
CHECK (nodeStr(43) == "i=43 lev:22 w=0 · · "_expect);
CHECK (nodeStr(44) == "i=44 lev:22 w=0 Σ6 Σw: 6"_expect);
CHECK (nodeStr(45) == "i=45 lev:23 w=0 · · "_expect);
CHECK (node[24]->level == 18); CHECK (node[24]->weight == 0);
CHECK (node[25]->level == 18); CHECK (node[25]->weight == 0);
CHECK (node[26]->level == 18); CHECK (node[26]->weight == 0);
CHECK (node[27]->level == 18); CHECK (node[27]->weight == 0);
CHECK (node[28]->level == 18); CHECK (node[28]->weight == 0); CHECK (getWeight(18) == 0);
CHECK (node[29]->level == 19); CHECK (node[29]->weight == 2);
CHECK (node[30]->level == 19); CHECK (node[30]->weight == 2);
CHECK (node[31]->level == 19); CHECK (node[31]->weight == 2);
CHECK (node[32]->level == 19); CHECK (node[32]->weight == 2);
CHECK (node[33]->level == 19); CHECK (node[33]->weight == 2); CHECK (getWeight(19) == 10);
CHECK (level[19].nodes = 5);
CHECK (level[19].weight = 10);
CHECK (computeWeightFactor(level[19], 1) == 10.0);
CHECK (computeWeightFactor(level[19], 2) == 10.0 / (5.0/3));
CHECK (computeWeightFactor(level[19], 3) == 10.0 / (5.0/2));
CHECK (computeWeightFactor(level[19], 4) == 10.0 / (5.0/2));
CHECK (computeWeightFactor(level[19], 5) == 10.0 / (5.0/1));
CHECK (node[34]->level == 20); CHECK (node[34]->weight == 3);
CHECK (node[35]->level == 20); CHECK (node[35]->weight == 2); CHECK (getWeight(20) == 5);
SHOW_EXPR(level.size())
uint concurrency = 4;
auto steps = testLoad.levelScheduleSequence(concurrency).effuse();
CHECK (steps.size() == 27);
CHECK (node[36]->level == 21); CHECK (node[36]->weight == 1);
CHECK (node[37]->level == 21); CHECK (node[37]->weight == 1);
CHECK (node[38]->level == 21); CHECK (node[38]->weight == 3); CHECK (getWeight(21) == 5);
auto boost = [&](uint i){ return level[i].nodes / std::ceil (double(level[i].nodes)/concurrency); };
auto wfact = [&](uint i){ return computeWeightFactor(level[i], concurrency); };
CHECK (levelWeights[19].nodes = 5);
CHECK (levelWeights[19].weight = 10);
CHECK (computeWeightFactor(levelWeights[19], 1) == 10.0);
CHECK (computeWeightFactor(levelWeights[19], 2) == 10.0 / (5.0/3));
CHECK (computeWeightFactor(levelWeights[19], 3) == 10.0 / (5.0/2));
CHECK (computeWeightFactor(levelWeights[19], 4) == 10.0 / (5.0/2));
CHECK (computeWeightFactor(levelWeights[19], 5) == 10.0 / (5.0/1));
_Fmt stepFmt{"lev:%-2d nodes:%-2d Σw:%2d %4.1f Δ%5.3f ▿▿ %6.3f"};
auto stepStr = [&](uint i){ return string{stepFmt % i % level[i].nodes % level[i].weight % boost(i) % wfact(i) % steps[i]}; };
CHECK (levelWeights[16].weight == 1); CHECK (levelWeights[16].nodes == 1); CHECK(scheduleSeq[16] == 13.0);
CHECK (levelWeights[17].weight == 3); CHECK (levelWeights[17].nodes == 1); CHECK(scheduleSeq[17] == 16.0);
CHECK (levelWeights[18].weight == 0); CHECK (levelWeights[18].nodes == 5); CHECK(scheduleSeq[18] == 16.0);
CHECK (levelWeights[19].weight ==10); CHECK (levelWeights[19].nodes == 5); CHECK(scheduleSeq[19] == 20.0);
CHECK (levelWeights[20].weight == 5); CHECK (levelWeights[20].nodes == 2); CHECK(scheduleSeq[20] == 22.5);
CHECK (stepStr( 0) == "lev:0 nodes:1 Σw: 0 1.0 Δ0.000 ▿▿ 0.000"_expect);
CHECK (stepStr( 1) == "lev:1 nodes:1 Σw: 0 1.0 Δ0.000 ▿▿ 0.000"_expect);
CHECK (stepStr( 2) == "lev:2 nodes:1 Σw: 2 1.0 Δ2.000 ▿▿ 2.000"_expect);
CHECK (stepStr( 3) == "lev:3 nodes:1 Σw: 0 1.0 Δ0.000 ▿▿ 2.000"_expect);
CHECK (stepStr( 4) == "lev:4 nodes:1 Σw: 0 1.0 Δ0.000 ▿▿ 2.000"_expect);
CHECK (stepStr( 5) == "lev:5 nodes:1 Σw: 0 1.0 Δ0.000 ▿▿ 2.000"_expect);
CHECK (stepStr( 6) == "lev:6 nodes:1 Σw: 1 1.0 Δ1.000 ▿▿ 3.000"_expect);
CHECK (stepStr( 7) == "lev:7 nodes:1 Σw: 2 1.0 Δ2.000 ▿▿ 5.000"_expect);
CHECK (stepStr( 8) == "lev:8 nodes:1 Σw: 2 1.0 Δ2.000 ▿▿ 7.000"_expect);
CHECK (stepStr( 9) == "lev:9 nodes:2 Σw: 2 2.0 Δ1.000 ▿▿ 8.000"_expect);
CHECK (stepStr(10) == "lev:10 nodes:2 Σw: 0 2.0 Δ0.000 ▿▿ 8.000"_expect);
CHECK (stepStr(11) == "lev:11 nodes:2 Σw: 0 2.0 Δ0.000 ▿▿ 8.000"_expect);
CHECK (stepStr(12) == "lev:12 nodes:2 Σw: 2 2.0 Δ1.000 ▿▿ 9.000"_expect);
CHECK (stepStr(13) == "lev:13 nodes:2 Σw: 2 2.0 Δ1.000 ▿▿ 10.000"_expect);
CHECK (stepStr(14) == "lev:14 nodes:2 Σw: 4 2.0 Δ2.000 ▿▿ 12.000"_expect);
CHECK (stepStr(15) == "lev:15 nodes:1 Σw: 0 1.0 Δ0.000 ▿▿ 12.000"_expect);
CHECK (stepStr(16) == "lev:16 nodes:1 Σw: 1 1.0 Δ1.000 ▿▿ 13.000"_expect);
CHECK (stepStr(17) == "lev:17 nodes:1 Σw: 3 1.0 Δ3.000 ▿▿ 16.000"_expect);
CHECK (stepStr(18) == "lev:18 nodes:5 Σw: 0 2.5 Δ0.000 ▿▿ 16.000"_expect);
CHECK (stepStr(19) == "lev:19 nodes:5 Σw:10 2.5 Δ4.000 ▿▿ 20.000"_expect);
CHECK (stepStr(20) == "lev:20 nodes:2 Σw: 5 2.0 Δ2.500 ▿▿ 22.500"_expect);
CHECK (stepStr(21) == "lev:21 nodes:3 Σw: 5 3.0 Δ1.667 ▿▿ 24.167"_expect);
CHECK (stepStr(22) == "lev:22 nodes:6 Σw: 6 3.0 Δ2.000 ▿▿ 26.167"_expect);
CHECK (stepStr(23) == "lev:23 nodes:6 Σw: 6 3.0 Δ2.000 ▿▿ 28.167"_expect);
CHECK (stepStr(24) == "lev:24 nodes:10 Σw: 9 3.3 Δ2.700 ▿▿ 30.867"_expect);
CHECK (stepStr(25) == "lev:25 nodes:2 Σw: 2 2.0 Δ1.000 ▿▿ 31.867"_expect);
CHECK (stepStr(26) == "lev:26 nodes:1 Σw: 1 1.0 Δ1.000 ▿▿ 32.867"_expect);
}

View file

@ -27,7 +27,7 @@
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
#include "lib/test/diagnostic-output.hpp"
#include "lib/format-string.hpp"
#include "test-chain-load.hpp"
#include "vault/gear/job.h"
#include "lib/util.hpp"
@ -35,6 +35,7 @@
#include <array>
using util::_Fmt;
using util::isnil;
using util::isSameObject;
using std::array;
@ -84,6 +85,7 @@ namespace test {
verify_computation_load();
verify_reseed_recalculate();
verify_runtime_reference();
verify_adjusted_schedule();
verify_scheduling_setup();
}
@ -1089,6 +1091,138 @@ namespace test {
/** @test verify use of computation weights and topology to establish
* a predicted load pattern, which can be used to construct a
* schedule adapted to the expected load.
* @remark use `printTopologyDOT()` and then `dot -Tpng xx.dot|display`
* to understand the numbers in context of the topology
*/
void
verify_adjusted_schedule()
{
TestChainLoad testLoad{64};
testLoad.configureShape_chain_loadBursts()
.buildToplolgy()
// .printTopologyDOT()
;
// compute aggregated level data....
auto level = testLoad.allLevelWeights().effuse();
CHECK (level.size() == 27);
// visualise and verify this data......
auto node = testLoad.allNodePtr().effuse();
_Fmt nodeFmt{"i=%-2d lev:%-2d w=%1d"};
_Fmt levelFmt{" Σ%-2d Σw:%2d"};
auto nodeStr = [&](uint i)
{
size_t l = node[i]->level;
return string{nodeFmt % i % node[i]->level % node[i]->weight}
+ (i == level[l].endidx? string{levelFmt % level[l].nodes % level[l].weight}
: string{" · · "});
};
// |idx--level--wght|-levelSum-------
CHECK (nodeStr( 1) == "i=1 lev:1 w=0 Σ1 Σw: 0"_expect);
CHECK (nodeStr( 2) == "i=2 lev:2 w=2 Σ1 Σw: 2"_expect);
CHECK (nodeStr( 3) == "i=3 lev:3 w=0 Σ1 Σw: 0"_expect);
CHECK (nodeStr( 4) == "i=4 lev:4 w=0 Σ1 Σw: 0"_expect);
CHECK (nodeStr( 5) == "i=5 lev:5 w=0 Σ1 Σw: 0"_expect);
CHECK (nodeStr( 6) == "i=6 lev:6 w=1 Σ1 Σw: 1"_expect);
CHECK (nodeStr( 7) == "i=7 lev:7 w=2 Σ1 Σw: 2"_expect);
CHECK (nodeStr( 8) == "i=8 lev:8 w=2 Σ1 Σw: 2"_expect);
CHECK (nodeStr( 9) == "i=9 lev:9 w=1 · · "_expect);
CHECK (nodeStr(10) == "i=10 lev:9 w=1 Σ2 Σw: 2"_expect);
CHECK (nodeStr(11) == "i=11 lev:10 w=0 · · "_expect);
CHECK (nodeStr(12) == "i=12 lev:10 w=0 Σ2 Σw: 0"_expect);
CHECK (nodeStr(13) == "i=13 lev:11 w=0 · · "_expect);
CHECK (nodeStr(14) == "i=14 lev:11 w=0 Σ2 Σw: 0"_expect);
CHECK (nodeStr(15) == "i=15 lev:12 w=1 · · "_expect);
CHECK (nodeStr(16) == "i=16 lev:12 w=1 Σ2 Σw: 2"_expect);
CHECK (nodeStr(17) == "i=17 lev:13 w=1 · · "_expect);
CHECK (nodeStr(18) == "i=18 lev:13 w=1 Σ2 Σw: 2"_expect);
CHECK (nodeStr(19) == "i=19 lev:14 w=2 · · "_expect);
CHECK (nodeStr(20) == "i=20 lev:14 w=2 Σ2 Σw: 4"_expect);
CHECK (nodeStr(21) == "i=21 lev:15 w=0 Σ1 Σw: 0"_expect);
CHECK (nodeStr(22) == "i=22 lev:16 w=1 Σ1 Σw: 1"_expect);
CHECK (nodeStr(23) == "i=23 lev:17 w=3 Σ1 Σw: 3"_expect);
CHECK (nodeStr(24) == "i=24 lev:18 w=0 · · "_expect);
CHECK (nodeStr(25) == "i=25 lev:18 w=0 · · "_expect);
CHECK (nodeStr(26) == "i=26 lev:18 w=0 · · "_expect);
CHECK (nodeStr(27) == "i=27 lev:18 w=0 · · "_expect);
CHECK (nodeStr(28) == "i=28 lev:18 w=0 Σ5 Σw: 0"_expect);
CHECK (nodeStr(29) == "i=29 lev:19 w=2 · · "_expect);
CHECK (nodeStr(30) == "i=30 lev:19 w=2 · · "_expect);
CHECK (nodeStr(31) == "i=31 lev:19 w=2 · · "_expect);
CHECK (nodeStr(32) == "i=32 lev:19 w=2 · · "_expect);
CHECK (nodeStr(33) == "i=33 lev:19 w=2 Σ5 Σw:10"_expect);
CHECK (nodeStr(34) == "i=34 lev:20 w=3 · · "_expect);
CHECK (nodeStr(35) == "i=35 lev:20 w=2 Σ2 Σw: 5"_expect);
CHECK (nodeStr(36) == "i=36 lev:21 w=1 · · "_expect);
CHECK (nodeStr(37) == "i=37 lev:21 w=1 · · "_expect);
CHECK (nodeStr(38) == "i=38 lev:21 w=3 Σ3 Σw: 5"_expect);
CHECK (nodeStr(39) == "i=39 lev:22 w=3 · · "_expect);
CHECK (nodeStr(40) == "i=40 lev:22 w=3 · · "_expect);
CHECK (nodeStr(41) == "i=41 lev:22 w=0 · · "_expect);
CHECK (nodeStr(42) == "i=42 lev:22 w=0 · · "_expect);
CHECK (nodeStr(43) == "i=43 lev:22 w=0 · · "_expect);
CHECK (nodeStr(44) == "i=44 lev:22 w=0 Σ6 Σw: 6"_expect);
CHECK (nodeStr(45) == "i=45 lev:23 w=0 · · "_expect);
// compute a weight factor for each level,
// using the number of nodes, the weight sum and concurrency
CHECK (level[19].nodes = 5); // ╭────────────────────────╢ concurrency
CHECK (level[19].weight = 10); // ▽ ╭───────╢ boost by concurrency
CHECK (computeWeightFactor(level[19], 1) == 10.0);// ▽
CHECK (computeWeightFactor(level[19], 2) == 10.0 / (5.0/3));
CHECK (computeWeightFactor(level[19], 3) == 10.0 / (5.0/2));
CHECK (computeWeightFactor(level[19], 4) == 10.0 / (5.0/2));
CHECK (computeWeightFactor(level[19], 5) == 10.0 / (5.0/1));
// build a schedule sequence based on
// summing up weight factors, with example concurrency ≔ 4
uint concurrency = 4;
auto steps = testLoad.levelScheduleSequence(concurrency).effuse();
CHECK (steps.size() == 27);
// for documentation/verification: show also the boost factor and the resulting weight factor
auto boost = [&](uint i){ return level[i].nodes / std::ceil (double(level[i].nodes)/concurrency); };
auto wfact = [&](uint i){ return computeWeightFactor(level[i], concurrency); };
_Fmt stepFmt{"lev:%-2d nodes:%-2d Σw:%2d %4.1f Δ%5.3f ▿▿ %6.3f"};
auto stepStr = [&](uint i){ return string{stepFmt % i % level[i].nodes % level[i].weight % boost(i) % wfact(i) % steps[i]}; };
// boost wfactor steps
CHECK (stepStr( 0) == "lev:0 nodes:1 Σw: 0 1.0 Δ0.000 ▿▿ 0.000"_expect);
CHECK (stepStr( 1) == "lev:1 nodes:1 Σw: 0 1.0 Δ0.000 ▿▿ 0.000"_expect);
CHECK (stepStr( 2) == "lev:2 nodes:1 Σw: 2 1.0 Δ2.000 ▿▿ 2.000"_expect);
CHECK (stepStr( 3) == "lev:3 nodes:1 Σw: 0 1.0 Δ0.000 ▿▿ 2.000"_expect);
CHECK (stepStr( 4) == "lev:4 nodes:1 Σw: 0 1.0 Δ0.000 ▿▿ 2.000"_expect);
CHECK (stepStr( 5) == "lev:5 nodes:1 Σw: 0 1.0 Δ0.000 ▿▿ 2.000"_expect);
CHECK (stepStr( 6) == "lev:6 nodes:1 Σw: 1 1.0 Δ1.000 ▿▿ 3.000"_expect);
CHECK (stepStr( 7) == "lev:7 nodes:1 Σw: 2 1.0 Δ2.000 ▿▿ 5.000"_expect);
CHECK (stepStr( 8) == "lev:8 nodes:1 Σw: 2 1.0 Δ2.000 ▿▿ 7.000"_expect);
CHECK (stepStr( 9) == "lev:9 nodes:2 Σw: 2 2.0 Δ1.000 ▿▿ 8.000"_expect);
CHECK (stepStr(10) == "lev:10 nodes:2 Σw: 0 2.0 Δ0.000 ▿▿ 8.000"_expect);
CHECK (stepStr(11) == "lev:11 nodes:2 Σw: 0 2.0 Δ0.000 ▿▿ 8.000"_expect);
CHECK (stepStr(12) == "lev:12 nodes:2 Σw: 2 2.0 Δ1.000 ▿▿ 9.000"_expect);
CHECK (stepStr(13) == "lev:13 nodes:2 Σw: 2 2.0 Δ1.000 ▿▿ 10.000"_expect);
CHECK (stepStr(14) == "lev:14 nodes:2 Σw: 4 2.0 Δ2.000 ▿▿ 12.000"_expect);
CHECK (stepStr(15) == "lev:15 nodes:1 Σw: 0 1.0 Δ0.000 ▿▿ 12.000"_expect);
CHECK (stepStr(16) == "lev:16 nodes:1 Σw: 1 1.0 Δ1.000 ▿▿ 13.000"_expect);
CHECK (stepStr(17) == "lev:17 nodes:1 Σw: 3 1.0 Δ3.000 ▿▿ 16.000"_expect);
CHECK (stepStr(18) == "lev:18 nodes:5 Σw: 0 2.5 Δ0.000 ▿▿ 16.000"_expect);
CHECK (stepStr(19) == "lev:19 nodes:5 Σw:10 2.5 Δ4.000 ▿▿ 20.000"_expect);
CHECK (stepStr(20) == "lev:20 nodes:2 Σw: 5 2.0 Δ2.500 ▿▿ 22.500"_expect);
CHECK (stepStr(21) == "lev:21 nodes:3 Σw: 5 3.0 Δ1.667 ▿▿ 24.167"_expect);
CHECK (stepStr(22) == "lev:22 nodes:6 Σw: 6 3.0 Δ2.000 ▿▿ 26.167"_expect);
CHECK (stepStr(23) == "lev:23 nodes:6 Σw: 6 3.0 Δ2.000 ▿▿ 28.167"_expect);
CHECK (stepStr(24) == "lev:24 nodes:10 Σw: 9 3.3 Δ2.700 ▿▿ 30.867"_expect);
CHECK (stepStr(25) == "lev:25 nodes:2 Σw: 2 2.0 Δ1.000 ▿▿ 31.867"_expect);
CHECK (stepStr(26) == "lev:26 nodes:1 Σw: 1 1.0 Δ1.000 ▿▿ 32.867"_expect);
}
/** @test setup for running a chain-load as scheduled task
* - running an isolated Node recalculation

View file

@ -174,6 +174,7 @@ namespace test {
{
size_t level{0};
size_t nodes{0};
size_t endidx{0};
size_t weight{0};
};
@ -779,10 +780,11 @@ namespace test {
{
return allNodes()
.groupedBy([](Node& n){ return n.level; }
,[](LevelWeight& lw, Node const& n)
,[this](LevelWeight& lw, Node const& n)
{
lw.level = n.level;
lw.weight += n.weight;
lw.endidx = nodeID(n);
++lw.nodes;
}
);

View file

@ -107586,7 +107586,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node COLOR="#338800" CREATED="1702944922179" ID="ID_424913055" MODIFIED="1703988524669" TEXT="Fall2: concurrent-X">
<icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1703794147800" ID="ID_875844018" MODIFIED="1703797733272" TEXT="schwierige Frage: wie die Last verteilen?">
<node COLOR="#435e98" CREATED="1703794147800" ID="ID_875844018" MODIFIED="1704055970353" TEXT="schwierige Frage: wie die Last verteilen?">
<icon BUILTIN="help"/>
<node CREATED="1703794161470" ID="ID_1249728332" MODIFIED="1703794182703" TEXT="&#xbb;box stacking problem&#xab;">
<node CREATED="1703794185949" ID="ID_134134437" MODIFIED="1703794208947" TEXT="optimale L&#xf6;sung ist nichttrivial"/>
@ -107601,6 +107601,10 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1703797666862" ID="ID_904711641" MODIFIED="1703797688398" TEXT="Ganz ensprechend dazu, da&#xdf; man auch keinen leer-Aufwand berechnet"/>
<node CREATED="1703797698137" ID="ID_1856874446" MODIFIED="1703797722175" TEXT="&#x27f9; eine reale Berechnung wird immer demgegen&#xfc;ber zur&#xfc;ckfallen"/>
</node>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1704055961258" ID="ID_559344426" MODIFIED="1704055968860" TEXT="in der Praxis bew&#xe4;hren">
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
</node>
</node>
<node COLOR="#435e98" CREATED="1703794695013" ID="ID_599869061" MODIFIED="1703794819987" TEXT="theoretischer Concurrency-Faktor">
<linktarget COLOR="#497dbb" DESTINATION="ID_599869061" ENDARROW="Default" ENDINCLINATION="-146;-288;" ID="Arrow_ID_312816279" SOURCE="ID_1945693212" STARTARROW="None" STARTINCLINATION="523;22;"/>
@ -107635,6 +107639,14 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="button_ok"/>
</node>
</node>
<node COLOR="#338800" CREATED="1704048358317" ID="ID_660577400" MODIFIED="1704055941213" TEXT="Dokumentation: in sinnvollen und gut lesbaren Test fassen">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1704048384760" ID="ID_1393867302" MODIFIED="1704048416222" TEXT="&#xd83e;&#xdc7a; TestChainLoad_test::verify_adjusted_schedule()"/>
<node CREATED="1704055893123" ID="ID_1058212370" MODIFIED="1704055916123" TEXT="verwende formatierte Strings pro Node oder pro Level"/>
<node CREATED="1704055924159" ID="ID_419522270" MODIFIED="1704055939063" TEXT="damit gleichzeitig lesbar und numerisch verifiziert">
<icon BUILTIN="idea"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1702945662283" ID="ID_557005311" MODIFIED="1702945685743" TEXT="M&#xf6;glichkeit f&#xfc;r hierauf abstellendes genaues Scheduling">
<icon BUILTIN="flag-yellow"/>