diff --git a/src/vault/gear/load-controller.hpp b/src/vault/gear/load-controller.hpp index 709823dfe..0dc04c52f 100644 --- a/src/vault/gear/load-controller.hpp +++ b/src/vault/gear/load-controller.hpp @@ -202,10 +202,11 @@ namespace gear { Capacity markOutgoingCapacity (Time head, Time now) { + if (head == Time::NEVER) return IDLEWAIT; // empty queue auto horizon = classifyTimeHorizon (Offset{head - now}); return horizon > SPINTIME and not tendedNext(head)? TENDNEXT - : horizon==IDLEWAIT ? WORKTIME + : horizon==IDLEWAIT ? WORKTIME // re-randomise sleeper cycles : horizon; } diff --git a/src/vault/gear/scheduler-invocation.hpp b/src/vault/gear/scheduler-invocation.hpp index b85e63723..db465dbbf 100644 --- a/src/vault/gear/scheduler-invocation.hpp +++ b/src/vault/gear/scheduler-invocation.hpp @@ -194,7 +194,7 @@ namespace gear { Time headTime() const { - return priority_.empty()? Time::ANYTIME + return priority_.empty()? Time::NEVER : Time{TimeValue{priority_.top().waterlevel}}; } //Note: 64-bit waterLevel corresponds to µ-Ticks diff --git a/tests/vault/gear/scheduler-service-test.cpp b/tests/vault/gear/scheduler-service-test.cpp index b2b89ca41..f62d8900b 100644 --- a/tests/vault/gear/scheduler-service-test.cpp +++ b/tests/vault/gear/scheduler-service-test.cpp @@ -35,6 +35,7 @@ //#include "lib/util.hpp" //#include +#include using test::Test; //using std::move; @@ -48,7 +49,14 @@ namespace test { // using lib::time::FrameRate; // using lib::time::Offset; using lib::time::Time; + using std::this_thread::sleep_for; + namespace { ////////////////////////////////////////////////////////////////////TICKET #1055 want to construct lumiera Time from std::chrono literals + Time t100us = Time{FSecs{1, 10'000}}; + Time t200us = t100us + t100us; + Time t500us = t200us + t200us + t100us; + Time t1ms = Time{1,0}; + } @@ -85,7 +93,13 @@ namespace test { - /** @test TODO verify visible behaviour of the work-pulling function + /** @test verify visible behaviour of the [work-pulling function](\ref Scheduler::getWork) + * - use a rigged Activity probe to capture the schedule time on invocation + * - additionally perform a timing measurement for invoking the work-function + * - empty invocations cost ~5µs (-O3) rsp. ~25µs (debug) + * - this implies we can show timing-delay effects in the millisecond range + * - demonstrated behaviour + * + an Activity already due will be dispatched immediately by post() * @todo WIP 10/23 🔁 define ⟶ implement */ void @@ -98,9 +112,24 @@ namespace test { ActivityDetector detector; Activity& probe = detector.buildActivationProbe ("testProbe"); - // this test class is declared friend to get a backdoor to Scheduler internals... - auto& schedCtx = Scheduler::ExecutionCtx::from(scheduler); + TimeVar start; + int64_t delay_us; + int64_t slip_us; + activity::Proc res; + + auto post = [&](Time start) + { // this test class is declared friend to get a backdoor to Scheduler internals... + auto& schedCtx = Scheduler::ExecutionCtx::from(scheduler); + + schedCtx.post (start, &probe, schedCtx); + }; + auto pullWork = [&] { + uint REPETITIONS = 1; + delay_us = lib::test::benchmarkTime([&]{ res = scheduler.getWork(); }, REPETITIONS); + slip_us = _raw(detector.invokeTime(probe)) - _raw(start); + cout << "res:"< up-front delay"< 500); + CHECK (delay_us < 1000); + pullWork(); +SHOW_EXPR(_raw(now)) +SHOW_EXPR(_raw(start)) +SHOW_EXPR(_raw(detector.invokeTime(probe))) +SHOW_EXPR(res); +SHOW_EXPR(delay_us) +SHOW_EXPR(slip_us) +SHOW_EXPR(wasInvoked(start)) + CHECK (wasInvoked(start)); + CHECK (delay_us < 200); + CHECK (slip_us < 500); + CHECK (activity::WAIT == res); + CHECK (scheduler.empty()); + + cout << "follow-up with some distance => follow-up delay"< 900); + CHECK (slip_us < 100); + CHECK (activity::PASS == res); + CHECK (not scheduler.empty()); + + start += t1ms; + pullWork(); +SHOW_EXPR(_raw(now)) +SHOW_EXPR(_raw(start)) +SHOW_EXPR(_raw(detector.invokeTime(probe))) +SHOW_EXPR(res); +SHOW_EXPR(delay_us) +SHOW_EXPR(slip_us) +SHOW_EXPR(wasInvoked(start)) +SHOW_EXPR(scheduler.empty()) + CHECK (wasInvoked(start)); + CHECK (delay_us < 500); + CHECK (slip_us < 500); + CHECK (activity::WAIT == res); + CHECK (scheduler.empty()); + cout << detector.showLog()< - - - + + + - - + + @@ -88196,11 +88196,72 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + + + + + + + + + + + + + + + +

+ also optimized vs. Debug-Build; ja man sieht diesen Unterschied im "slip", weil einfach die Verarbeitung länger dauert +

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

+ habe generell hier den Fall der leeren Queue nicht bedacht +

+ + +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + @@ -88243,6 +88304,18 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + +