Scheduler-test: design problems impeding clean test-setup

Encountering ''just some design problems related to the test setup,''
which however turn out hard to overcome. Seems that, in my eagerness
to create a succinct and clear presentation of the test, I went into
danger territory, overstretching the abilities of the C++ language.

After working with a set of tools created step by step over an extended span of time,
''for me'' the machinations of this setup seem to be reduced to flipping a toggle
here and there, and I want to focus these active parts while laying out this test.
''This would require'' to create a system of nested scopes, while getting more and more
specific gradually, and moving to the individual case at question; notably any
clarification and definition within those inner focused contexts would have to be
picked up and linked in dynamically.

Yet the C++ language only allows to be ''either'' open and flexible towards
the actual types, or ''alternatively'' to select dynamically within a fixed
set of (virtual) methods, which then must be determined from the beginning.
It is not possible to tweak and adjust base definitions after the fact,
and it is not possible to fill in constant definitions dynamically
with late binding to some specific implementation type provided only
at current scope.

Seems that I am running against that brick wall over and over again,
piling up complexities driven by an desire for succinctness and clarity.

Now attempting to resolve this quite frustrating situation...
- fix the actual type of the TestChainLoad by a typedef in test context
- avoid the definitions (and thus the danger of shadowing)
  and use one `testSetup()` method to place all local adjustments.
This commit is contained in:
Fischlurch 2024-04-06 23:21:10 +02:00
parent d47f24d745
commit 10fa0aaa79
4 changed files with 100 additions and 34 deletions

View file

@ -329,6 +329,7 @@ namespace test {
} // should ideally spend most of the time at highest concurrency levels
using StressRig = StressTestRig<16>;
/** @test determine the breaking point towards scheduler overload
* - use the integrated StressRig
@ -356,11 +357,18 @@ namespace test {
struct Setup : StressRig
{
usec LOAD_BASE = 500us;
uint CONCURRENCY = 4;
bool showRuns = true;
auto testLoad() { return TestChainLoad<>{64}.configureShape_chain_loadBursts(); }
auto testLoad()
{ return TestLoad{64}.configureShape_chain_loadBursts(); }
auto testSetup (TestLoad& testLoad)
{
return StressRig::testSetup(testLoad)
.withLoadTimeBase(500us);
}
};
auto [stress,delta,time] = StressRig::with<Setup>()
@ -391,19 +399,23 @@ namespace test {
struct Setup : StressRig
{
usec LOAD_BASE = 500us;
uint CONCURRENCY = 4;
using Param = size_t;
using Table = bench::DataTable<Param>;
auto
testLoad(Param nodes)
auto testLoad(Param nodes)
{
TestChainLoad testLoad{nodes};
TestLoad testLoad{nodes};
return testLoad.configure_isolated_nodes();
}
auto testSetup (TestLoad& testLoad)
{
return StressRig::testSetup(testLoad)
.withLoadTimeBase(500us);
}
void
collectResult(Table& data, Param param, double millis, bench::IncidenceStat const& stat)
{
@ -469,11 +481,10 @@ SHOW_EXPR(loadMicros)
//SHOW_EXPR(runTime)
//SHOW_EXPR(expected)
//SHOW_EXPR(refTime)
using StressRig = StressTestRig<8>;
struct Setup : StressRig
{
usec LOAD_BASE = 500us;
usec BASE_EXPENSE = 200us;
double UPPER_STRESS = 12;
//
double FAIL_LIMIT = 1.0; //0.7;
@ -486,13 +497,20 @@ SHOW_EXPR(loadMicros)
auto
testLoad()
{
TestChainLoad<8> testLoad{256};
TestLoad testLoad{256};
testLoad.seedingRule(testLoad.rule().probability(0.6).minVal(2))
.pruningRule(testLoad.rule().probability(0.44))
.weightRule(testLoad.value(1))
.setSeed(55);
return testLoad;
}
auto testSetup (TestLoad& testLoad)
{
return StressRig::testSetup(testLoad)
.withBaseExpense(200us)
.withLoadTimeBase(500us);
}
};
auto [stress,delta,time] = StressRig::with<Setup>()
.perform<bench::BreakingPoint>();

View file

@ -143,11 +143,15 @@ namespace test {
/** configurable template framework for running Scheduler Stress tests */
class StressRig
template<size_t maxFan =DEFAULT_FAN>
class StressTestRig
: util::NonCopyable
{
public:
using TestLoad = TestChainLoad<maxFan>;
using TestSetup = typename TestLoad::ScheduleCtx;
/***********************************************************************//**
* Entrance Point: build a stress test measurement setup using a dedicated
* \a TOOL class, takes the configuration \a CONF as template parameter
@ -165,13 +169,6 @@ namespace test {
/* ======= default configuration (inherited) ======= */
using usec = std::chrono::microseconds;
usec LOAD_BASE = 500us;
usec LEVEL_STEP = 200us;
usec BASE_EXPENSE = 0us;
bool SCHED_NOTIFY = true;
bool SCHED_DEPENDS = false;
uint CONCURRENCY = work::Config::getDefaultComputationCapacity();
bool INSTRUMENTATION = true;
double EPSILON = 0.01; ///< error bound to abort binary search
@ -198,20 +195,16 @@ namespace test {
auto
testLoad(size_t nodes =64)
{
return TestChainLoad<>{nodes};
return TestLoad{nodes};
}
/** (optional) extension point: base configuration of the test ScheduleCtx */
template<class TL>
/** (optional) extension point: base configuration of the test ScheduleCtx
* @warning the actual setup \a CONF is layered, beware of shadowing. */
auto
testSetup (TL& testLoad)
testSetup (TestLoad& testLoad)
{
return testLoad.setupSchedule(scheduler)
.withLoadTimeBase(LOAD_BASE)
.withLevelDuration(LEVEL_STEP)
.withBaseExpense (BASE_EXPENSE)
.withSchedNotify (SCHED_NOTIFY)
.withSchedDepends(SCHED_DEPENDS)
.withLevelDuration(200us)
.withJobDeadline(100ms)
.withUpfrontPlanning();
}
@ -244,8 +237,8 @@ namespace test {
class BreakingPoint
: public CONF
{
using TestLoad = decltype(declval<BreakingPoint>().testLoad());
using TestSetup = decltype(declval<BreakingPoint>().testSetup (declval<TestLoad&>()));
using TestLoad = typename CONF::TestLoad;
using TestSetup = typename TestLoad::ScheduleCtx;
struct Res
{
@ -383,11 +376,11 @@ namespace test {
}
void
showRef(TestLoad& testLoad)
showRef(TestSetup& testSetup)
{
if (CONF::showRef)
cout << fmtResVal_ % "refTime"
% (testLoad.calcRuntimeReference(CONF::LOAD_BASE) /1000)
% (testSetup.calcRuntimeReference() /1000)
% "ms" << endl;
}
@ -417,7 +410,7 @@ namespace test {
Res res = conductBinarySearch (move(performEvaluation), observations);
showRes (res);
showRef (testLoad);
showRef (testSetup);
return make_tuple (res.stressFac, res.avgDelta, res.avgTime);
}
};
@ -465,8 +458,8 @@ namespace test {
using Table = typename CONF::Table;
using Param = typename CONF::Param;
using TestLoad = decltype(declval<ParameterRange>().testLoad(Param()));
using TestSetup = decltype(declval<ParameterRange>().testSetup (declval<TestLoad&>()));
using TestLoad = typename CONF::TestLoad;
using TestSetup = typename TestLoad::ScheduleCtx;
void

View file

@ -1865,6 +1865,14 @@ namespace test {
: lib::IncidenceCount::Statistic{};
}
double
calcRuntimeReference()
{
microseconds timeBase = compuLoad_->timeBase;
size_t sizeBase = compuLoad_->useAllocation? compuLoad_->sizeBase : 0;
return chainLoad_.calcRuntimeReference (timeBase, sizeBase);
}
double getStressFac() { return stressFac_; }

View file

@ -114935,11 +114935,58 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
</node>
</node>
</node>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1712370539491" ID="ID_1967428575" MODIFIED="1712370557205" TEXT="Layered Setup wird zunehmend problematisch">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1712370558825" ID="ID_1505316994" MODIFIED="1712370586641" TEXT="Widerspruch virtuell &#x27f7; generisch"/>
<node CREATED="1712370587541" ID="ID_1522410406" MODIFIED="1712370603477" TEXT="was ich eigentlich m&#xf6;chte: &#xbb;hier zur Hand&#xab;">
<icon BUILTIN="idea"/>
<node CREATED="1712370607514" ID="ID_419615452" MODIFIED="1712370615573" TEXT="in diesem konkreten Kontext"/>
<node CREATED="1712370616161" ID="ID_1073937892" MODIFIED="1712370628412" TEXT="mit allen Einzelfall-Anpassungen"/>
<node CREATED="1712370629312" ID="ID_1738241347" MODIFIED="1712370638602" TEXT="welche aber auf einem allgemeineren Schema aufsetzen"/>
</node>
<node CREATED="1712370655378" ID="ID_205661748" MODIFIED="1712370660087" TEXT="rein formal-technisch">
<node CREATED="1712370665227" ID="ID_1870575473" MODIFIED="1712370678645" TEXT="...w&#xfc;rde das nach einem dynamischen Scope verlangen"/>
<node CREATED="1712370682448" ID="ID_481728399" MODIFIED="1712370697486" TEXT="in dem auf allen Ebenen noch Methoden und Konstanten &#xfc;berlagert werden k&#xf6;nnen"/>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1712370716979" ID="ID_923685396" MODIFIED="1712438645589" TEXT="dem stehen Limitierungen der Sprache im Wege">
<icon BUILTIN="broken-line"/>
<node CREATED="1712438658067" ID="ID_108928226" MODIFIED="1712438666881" TEXT="keine Reflection"/>
<node CREATED="1712438674412" ID="ID_833076441" MODIFIED="1712438688559" TEXT="keine Auswertungen auf Klassen-Scope"/>
<node CREATED="1712438789271" ID="ID_806153717" MODIFIED="1712438802545" TEXT="kein dynamisches/late-Binding"/>
<node CREATED="1712438689506" ID="ID_1955664487" MODIFIED="1712438738745" TEXT="Template vs. VTable"/>
</node>
<node CREATED="1712438760082" ID="ID_97703658" MODIFIED="1712438843180" TEXT="die bestehende Struktur versucht diese Limitierungen zu umschiffen">
<node CREATED="1712438854479" ID="ID_892223823" MODIFIED="1712438877962" TEXT="das ist potentiell gef&#xe4;hrlich"/>
<node CREATED="1712438878693" ID="ID_1350971341" MODIFIED="1712438912614" TEXT="und verhindert das Mischen von Konstanten und default-Methoden"/>
</node>
<node CREATED="1712438940621" ID="ID_567981926" MODIFIED="1712439567292" TEXT="Richtlinie &#x27f9; Konfiguration in testSetup()-Methode verlagern">
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1712443577073" ID="ID_392914682" MODIFIED="1712443583609" TEXT="brauche daf&#xfc;r eine klare Notation">
<icon BUILTIN="flag-pink"/>
<node CREATED="1712443590806" ID="ID_1885394541" MODIFIED="1712443606819" TEXT="Idee: Setup-Datentyp">
<icon BUILTIN="idea"/>
</node>
</node>
</node>
</node>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1712190783314" ID="ID_561451802" MODIFIED="1712238531623" TEXT="Gnuplot-Skript generieren">
<linktarget COLOR="#4a8bb7" DESTINATION="ID_561451802" ENDARROW="Default" ENDINCLINATION="330;-389;" ID="Arrow_ID_787725069" SOURCE="ID_109820250" STARTARROW="None" STARTINCLINATION="191;23;"/>
<icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1712364733453" ID="ID_1252919239" MODIFIED="1712364934156" TEXT="setup in HIlfsfunktion im Stress-Test-Rig verlagen">
<icon BUILTIN="flag-yellow"/>
</node>
<node CREATED="1712364714975" ID="ID_1343230425" MODIFIED="1712364731729" TEXT="Anpassungen">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1712364780151" ID="ID_1769816620" MODIFIED="1712364932636" TEXT="Regressions-Parameter anzeigen">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1712364901190" ID="ID_1416417622" MODIFIED="1712364932644" TEXT="sinnvolles tick-spacing f&#xfc;r diese Messung">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1712364920076" ID="ID_719755566" MODIFIED="1712364932645" TEXT="Achsenbeschriftungen vorbelegen">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
</node>
</node>