Fix scheduler benchmark: use fake time with guard disabled at compile time

interval=0 causes infinite loop (reschedules at same time, never breaks).
interval=1 with millis() doesn't work (real time doesn't advance fast
enough between inner iterations for intervals to re-fire).

Solution: use interval=1 with monotonically increasing fake time (now++)
and disable WarnIfComponentBlockingGuard at compile time via
-DWARN_IF_BLOCKING_OVER_MS=UINT32_MAX in benchmark build flags. This
prevents the guard's (millis() - started_) underflow when fake time
exceeds real millis().
This commit is contained in:
J. Nick Koston
2026-03-17 01:00:06 -10:00
parent d7be19703b
commit ec60e2c228
2 changed files with 14 additions and 6 deletions
+4
View File
@@ -34,6 +34,10 @@ PLATFORMIO_OPTIONS = {
"-O2", # optimize for speed (CodSpeed recommends RelWithDebInfo)
"-g", # debug symbols for profiling
USE_TIME_TIMEZONE_FLAG,
# Disable WarnIfComponentBlockingGuard check — scheduler benchmarks
# use fake monotonic time ahead of real millis(), causing uint32_t
# underflow in the guard's (millis() - started_) calculation.
"-DWARN_IF_BLOCKING_OVER_MS=UINT32_MAX",
],
# Use deep+ LDF mode to ensure PlatformIO detects the benchmark
# library dependency from nested includes.
+10 -6
View File
@@ -66,18 +66,22 @@ static void Scheduler_Call_5IntervalsFiring(benchmark::State &state) {
BenchComponent dummy_component;
int fire_count = 0;
// Add 5 intervals with 0ms period — they fire every call() unconditionally.
// WarnIfComponentBlockingGuard compares the `now` we pass against real
// millis() in finish(), so we must pass real millis() to avoid underflow.
// With interval=0, all 5 fire every call without needing to advance time.
// Add 5 intervals with 1ms period — they fire every call when time advances.
// We use monotonically increasing fake time (now++) so intervals reliably fire.
// WARN_IF_BLOCKING_OVER_MS=UINT32_MAX in benchmark build flags prevents the
// WarnIfComponentBlockingGuard from triggering when fake time exceeds real millis().
// Note: interval=0 causes an infinite loop (reschedules at same time, never breaks).
for (int i = 0; i < 5; i++) {
scheduler.set_interval(&dummy_component, static_cast<uint32_t>(i), 0, [&fire_count]() { fire_count++; });
scheduler.set_interval(&dummy_component, static_cast<uint32_t>(i), 1, [&fire_count]() { fire_count++; });
}
scheduler.process_to_add();
uint32_t now = millis() + 100;
for (auto _ : state) {
for (int i = 0; i < kInnerIterations; i++) {
scheduler.call(millis());
scheduler.call(now);
now++;
}
benchmark::DoNotOptimize(fire_count);
}