diff --git a/src/lib/util.hpp b/src/lib/util.hpp index e915660b4..981f3aaa5 100644 --- a/src/lib/util.hpp +++ b/src/lib/util.hpp @@ -52,21 +52,21 @@ namespace util { template - inline int + inline int constexpr sgn (NUM n) { return (n==0)? 0 :((n<0)? -1:+1 ); } template - inline N1 + inline N1 constexpr min (N1 n1, N2 n2) { return n2 < n1? N1(n2) : n1; } template - inline N1 + inline N1 constexpr max (N1 n1, N2 n2) { return n1 < n2? N1(n2) : n1; @@ -74,7 +74,7 @@ namespace util { /** cut a numeric value to be >=0 */ template - inline NUM + inline NUM constexpr noneg (NUM val) { return (0 - inline NUM + inline NUM constexpr limited (NB lowerBound, NUM val, NB upperBound) { return min ( max (val, lowerBound) diff --git a/src/vault/gear/load-controller.hpp b/src/vault/gear/load-controller.hpp index 6068df373..329220c91 100644 --- a/src/vault/gear/load-controller.hpp +++ b/src/vault/gear/load-controller.hpp @@ -152,8 +152,7 @@ namespace gear { public: struct Wiring { - size_t maxCapacity{2}; - + function maxCapacity {[]{ return 1; }}; function currWorkForceSize{[]{ return 0; }}; ///////TODO add here functors to access performance indicators }; @@ -189,7 +188,7 @@ namespace gear { double lag = _raw(std::clamp (now - (head.isRegular()? head:now) , -SLEEP_HORIZON , WORK_HORIZON)); - const double alpha = LAG_SAMPLE_DAMPING / (1 + wiring_.maxCapacity); + const double alpha = LAG_SAMPLE_DAMPING / (1 + wiring_.maxCapacity()); int64_t average = sampledLag_.load (memory_order_relaxed); int64_t newAverage; do newAverage = std::floor (lag*alpha + (1-alpha)*average); @@ -238,7 +237,7 @@ namespace gear { lag /= _raw(WORK_HORIZON); lag *= 10; double lagFactor = lag<0? 1/(1-lag): 1+lag; - double loadFactor = wiring_.currWorkForceSize() / double(wiring_.maxCapacity); + double loadFactor = wiring_.currWorkForceSize() / double(wiring_.maxCapacity()); return loadFactor * lagFactor; } diff --git a/src/vault/gear/scheduler.hpp b/src/vault/gear/scheduler.hpp index 9d78ef947..ad702dccc 100644 --- a/src/vault/gear/scheduler.hpp +++ b/src/vault/gear/scheduler.hpp @@ -360,7 +360,7 @@ namespace gear { connectMonitoring() { LoadController::Wiring setup; - setup.maxCapacity = work::Config::COMPUTATION_CAPACITY; + setup.maxCapacity = []{ return work::Config::COMPUTATION_CAPACITY; }; setup.currWorkForceSize = [this]{ return workForce_.size(); }; return setup; } diff --git a/src/vault/gear/work-force.cpp b/src/vault/gear/work-force.cpp index 442f0daa1..55b944480 100644 --- a/src/vault/gear/work-force.cpp +++ b/src/vault/gear/work-force.cpp @@ -23,27 +23,14 @@ /** @file work-force.cpp ** Implementation of render worker coordination. ** - ** @note as of X/2023 this is complete bs - ** @todo WIP ///////////////////////TICKET # - ** - ** @see ////TODO_test usage example - ** @see scheduler.cpp implementation - ** - ** @todo WIP-WIP-WIP 6/2023 »Playback Vertical Slice« + ** @todo WIP-WIP 11/2023 »Playback Vertical Slice« ** */ #include "vault/gear/work-force.hpp" -//#include "lib/symbol.hpp" -//#include "include/logging.h" #include "lib/util.hpp" -//#include - -//using std::string; -//using util::isnil; - namespace vault{ namespace gear { @@ -56,15 +43,24 @@ namespace gear { -// NA::~NA() { } - - /** default value for full computing capacity is to use all (virtual) cores */ - const size_t work::Config::COMPUTATION_CAPACITY = util::max (std::thread::hardware_concurrency() - , MINIMAL_CONCURRENCY); - - + /** + * Nominal »full size« of a pool of concurrent workers. + * This value is [initialised](\ref Config::getDefaultComputationCapacity) + * to use all available concurrent computing cores, but can be adjusted. + * Adjustments should be done before a worker pool scales up. + * @warning this value is taken as-is; setting it to zero will disable + * many (but not all) aspects of concurrent processing. + */ + size_t work::Config::COMPUTATION_CAPACITY = Config::getDefaultComputationCapacity(); /** + * default value for full computing capacity is to use all (virtual) cores. */ + size_t + work::Config::getDefaultComputationCapacity() + { + return util::max (std::thread::hardware_concurrency() + , MINIMAL_CONCURRENCY); + } }} // namespace vault::gear diff --git a/src/vault/gear/work-force.hpp b/src/vault/gear/work-force.hpp index 9f7978a53..a9a565f2c 100644 --- a/src/vault/gear/work-force.hpp +++ b/src/vault/gear/work-force.hpp @@ -95,10 +95,12 @@ namespace gear { */ struct Config { - static const size_t COMPUTATION_CAPACITY; + static size_t COMPUTATION_CAPACITY; const milliseconds IDLE_WAIT = 20ms; const size_t DISMISS_CYCLES = 100; + + static size_t getDefaultComputationCapacity(); }; diff --git a/tests/vault/gear/scheduler-load-control-test.cpp b/tests/vault/gear/scheduler-load-control-test.cpp index 9923fcdcd..094b9eaf1 100644 --- a/tests/vault/gear/scheduler-load-control-test.cpp +++ b/tests/vault/gear/scheduler-load-control-test.cpp @@ -316,7 +316,7 @@ namespace test { uint currThreads = 0; LoadController::Wiring setup; - setup.maxCapacity = maxThreads; + setup.maxCapacity = [&]{ return maxThreads; }; setup.currWorkForceSize = [&]{ return currThreads; }; // rigged setup to verify calculated load indicator LoadController lctrl{move(setup)}; diff --git a/tests/vault/gear/scheduler-service-test.cpp b/tests/vault/gear/scheduler-service-test.cpp index 73008e630..fa78239e5 100644 --- a/tests/vault/gear/scheduler-service-test.cpp +++ b/tests/vault/gear/scheduler-service-test.cpp @@ -80,10 +80,10 @@ namespace test { virtual void run (Arg) { - simpleUsage(); - verify_StartStop(); - verify_LoadFactor(); - invokeWorkFunction(); +// simpleUsage(); +// verify_StartStop(); +// verify_LoadFactor(); +// invokeWorkFunction(); scheduleRenderJob(); walkingDeadline(); } @@ -464,24 +464,27 @@ namespace test { ////////////////////////////////// CHECK (scheduler.empty()); SHOW_EXPR(offset()) + auto buidl= scheduler.defineSchedule(testJob) .startOffset(200us) - .lifeWindow (1ms) - .manifestation(ManifestationID{55}) - .post(); + .lifeWindow (1ms); +SHOW_EXPR(offset()) + buidl .post(); CHECK (not scheduler.empty()); - CHECK (detector.ensureNoInvocation("testJob")); +// CHECK (detector.ensureNoInvocation("testJob")); SHOW_EXPR(offset()) sleep_for(400us); - CHECK (detector.ensureNoInvocation("testJob")); +// CHECK (detector.ensureNoInvocation("testJob")); SHOW_EXPR(offset()) - + scheduler.layer1_.feedPrioritisation(); auto res= scheduler.getWork(); -SHOW_EXPR(res) +SHOW_EXPR(offset()) +SHOW_EXPR(res) +SHOW_EXPR(offset(scheduler.layer1_.headTime())) // CHECK (activity::PASS == scheduler.getWork()); - CHECK (scheduler.empty()); +// CHECK (scheduler.empty()); cout << detector.showLog()< + + + + + + + + + + + + + + @@ -82669,6 +82683,37 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + + + + + + + + + + +

+ ....also kein Locking etc; allerdings greift der LoadController jetzt per Lambda darauf zu. +

+ + +
+
+ + + +
@@ -82910,6 +82955,73 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + + + + + + + + + + + + + +

+ ...im Lastbetrieb möchte man das eigentlich auch nicht: ein ankommender Thread soll gemäß aktueller Situation klassifiziert werden, aber nicht erst mal um das Grooming-Token konkurrieren +

+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ ....und das würde in dem Fall das Problem durch den ersten »Tick« nebenbei beheben — aber nicht, falls der Scheduler bereits läuft und leer gefallen ist +

+ + +
+ +
+
+
+
@@ -84099,7 +84211,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + @@ -84154,13 +84267,35 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + +
+ + + + + + + + + + + +

+ daher muß für einen neuen Job ein step up erfolgen +

+ + +
+ +
+ +
@@ -84302,6 +84437,30 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + + + + + + + + + + + + + + @@ -84920,7 +85079,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -87392,7 +87551,11 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + + + @@ -92249,11 +92412,43 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + + + + + + + + + + +

+ Aus Sicht des Testaufbaues wäre es sehr wünschenswert. Aber da das Scheduler-API high-Level ist, sehe ich keine einfache Möglichkeit, für einen Test dazwischen zu gehen. Ein Mocking / Austauschen des Scheduler wäre hier nicht zielführend (weil es genau auf die Interaktion mit der integrierten Scheduler-Implementierung ankommt). +

+ +
+
+ + + + + + + + + + + + + + + + +