Merge branch 'mdns-throttle-update-polling' into integration

This commit is contained in:
J. Nick Koston
2026-02-10 14:30:24 -06:00
3 changed files with 44 additions and 2 deletions
+22
View File
@@ -48,6 +48,25 @@ class MDNSComponent : public Component {
#if (defined(USE_ESP8266) || defined(USE_RP2040)) && defined(USE_ARDUINO)
void loop() override;
#endif
// Throttle interval for MDNS.update() on platforms that require polling (ESP8266, RP2040).
//
// On these platforms, MDNS.update() calls _process(true) which only manages timer-driven
// state machines (probe/announce timeouts and service query cache TTLs). Incoming mDNS
// packets are handled independently via the lwIP onRx UDP callback and are NOT affected
// by how often update() is called.
//
// The shortest internal timer is the 250ms probe interval (RFC 6762 Section 8.1).
// Announcement intervals are 1000ms and cache TTL checks are on the order of seconds
// to minutes. A 50ms polling interval provides sufficient resolution for all timers
// while reducing CPU overhead by ~84% compared to calling every loop iteration.
//
// In steady state (after the ~8 second boot probe/announce phase completes), update()
// checks timers that are set to never expire, making every call pure overhead.
//
// Tasmota uses a 50ms main loop cycle with mDNS working correctly, confirming this
// interval is safe in production.
static constexpr uint32_t MDNS_UPDATE_INTERVAL_MS = 50;
float get_setup_priority() const override { return setup_priority::AFTER_CONNECTION; }
#ifdef USE_MDNS_EXTRA_SERVICES
@@ -110,6 +129,9 @@ class MDNSComponent : public Component {
#endif
#ifdef USE_MDNS_STORE_SERVICES
StaticVector<MDNSService, MDNS_SERVICE_COUNT> services_{};
#endif
#if (defined(USE_ESP8266) || defined(USE_RP2040)) && defined(USE_ARDUINO)
uint32_t last_update_{0};
#endif
void compile_records_(StaticVector<MDNSService, MDNS_SERVICE_COUNT> &services, char *mac_address_buf);
};
+11 -1
View File
@@ -38,7 +38,17 @@ static void register_esp8266(MDNSComponent *, StaticVector<MDNSService, MDNS_SER
void MDNSComponent::setup() { this->setup_buffers_and_register_(register_esp8266); }
void MDNSComponent::loop() { MDNS.update(); }
void MDNSComponent::loop() {
// Throttle MDNS.update() to avoid calling it every loop iteration (~120 Hz).
// The update() function only manages timer-driven probe/announce state machines
// and service query cache TTLs. Incoming mDNS packets are processed independently
// via the lwIP onRx callback and do not depend on update() frequency.
const uint32_t now = App.get_loop_component_start_time();
if (now - this->last_update_ < MDNS_UPDATE_INTERVAL_MS)
return;
this->last_update_ = now;
MDNS.update();
}
void MDNSComponent::on_shutdown() {
MDNS.close();
+11 -1
View File
@@ -37,7 +37,17 @@ static void register_rp2040(MDNSComponent *, StaticVector<MDNSService, MDNS_SERV
void MDNSComponent::setup() { this->setup_buffers_and_register_(register_rp2040); }
void MDNSComponent::loop() { MDNS.update(); }
void MDNSComponent::loop() {
// Throttle MDNS.update() to avoid calling it every loop iteration (~120 Hz).
// The update() function only manages timer-driven probe/announce state machines
// and service query cache TTLs. Incoming mDNS packets are processed independently
// via the lwIP onRx callback and do not depend on update() frequency.
const uint32_t now = App.get_loop_component_start_time();
if (now - this->last_update_ < MDNS_UPDATE_INTERVAL_MS)
return;
this->last_update_ = now;
MDNS.update();
}
void MDNSComponent::on_shutdown() {
MDNS.close();