[core] raise WDT_FEED_INTERVAL_MS from 3 to 300

The 3 ms rate limit was tight enough that the outer feed_wdt_with_time()
at the top of Application::loop() hit the slow path on nearly every
iteration. On-device measurements showed 95-99.9% of iterations
triggering esp_task_wdt_reset(), costing ~9-12 us/hit (BT proxies worse
due to WDT spinlock contention with the BT task on the other core).

Much worse under wake-storm workloads: with loop_interval_ raised for
power saving and an external stack (OpenThread in the reported case)
posting frequent wake notifications, the main loop can spin at thousands
of Hz doing almost nothing but feeding the watchdog — burning ~26% CPU
in the extreme case reported on #15792.

Raising the threshold to 300 ms:
  - Normal 62 Hz loop: feeds once every ~19 iterations (~3 Hz) instead
    of every iteration.
  - Wake-storm case: feeds ~3 Hz regardless of wake rate.
  - Any operation exceeding 300 ms still triggers a real feed right
    after it finishes (the post-component and post-scheduler-item
    feeds naturally clear the gate).

Safety margins vs platform watchdog timeouts remain large: 16x on ESP32
(5 s task WDT), 5x on ESP8266 soft WDT (1.6 s), 20x on ESP8266 HW WDT.
This commit is contained in:
J. Nick Koston
2026-04-18 17:01:17 -05:00
parent 4e05d39f4b
commit f29da222fe
+11 -4
View File
@@ -229,10 +229,17 @@ class Application {
void schedule_dump_config() { this->dump_config_at_ = 0; }
/// Minimum interval between real arch_feed_wdt() calls. Chosen to keep the
/// rate of HAL pokes low while still being small enough that any plausible
/// watchdog timeout (seconds) has orders of magnitude of safety margin.
static constexpr uint32_t WDT_FEED_INTERVAL_MS = 3;
/// Minimum interval between real arch_feed_wdt() calls. Sized so the outer
/// feed in Application::loop() is effectively rate-limited across both the
/// normal ~62 Hz cadence and worst-case wake-storm scenarios (e.g. external
/// stacks like OpenThread posting frequent wake notifications). Component
/// loops and scheduler items still feed after every op, so any op exceeding
/// this threshold triggers a real feed naturally.
/// Safety margins vs. platform watchdog timeouts:
/// - ESP32 task WDT default (5 s): ~16x
/// - ESP8266 soft WDT (~1.6 s): ~5x
/// - ESP8266 HW WDT (~6 s): ~20x
static constexpr uint32_t WDT_FEED_INTERVAL_MS = 300;
/// Feed the task watchdog. Cold entry — callers without a millis()
/// timestamp in hand. Out of line to keep call sites tiny.