Skip update_connected_state_() when no events and already connected

wifi_sta_connect_status_() is a non-inlined function call that reads
3 static globals through literal pool indirections on every loop
iteration. Since those globals are only modified during event
processing, skip the call entirely when wifi_loop_() found no
events and we're already in STA_CONNECTED state.

wifi_loop_() now returns bool (true if events were processed) on
all platforms. ESP8266 and Pico W always return true since they
poll state directly rather than using an event queue.
This commit is contained in:
J. Nick Koston
2026-04-01 12:27:39 -10:00
parent 20884d5844
commit f7222e39bb
6 changed files with 20 additions and 9 deletions
+7 -2
View File
@@ -730,9 +730,14 @@ void WiFiComponent::restart_adapter() {
}
void WiFiComponent::loop() {
this->wifi_loop_();
bool events_processed = this->wifi_loop_();
const uint32_t now = App.get_loop_component_start_time();
this->update_connected_state_();
// Connection state can only change when events are processed (ESP-IDF/LibreTiny)
// or polled (ESP8266/Pico W). Skip the expensive wifi_sta_connect_status_() call
// when no events arrived and we're already in steady state.
if (events_processed || this->state_ != WIFI_COMPONENT_STATE_STA_CONNECTED) {
this->update_connected_state_();
}
if (this->has_sta()) {
#if defined(USE_WIFI_CONNECT_TRIGGER) || defined(USE_WIFI_DISCONNECT_TRIGGER)
+1 -1
View File
@@ -662,7 +662,7 @@ class WiFiComponent final : public Component {
void connect_soon_();
void wifi_loop_();
bool wifi_loop_();
#ifdef USE_ESP8266
void process_pending_callbacks_();
#endif
@@ -938,7 +938,10 @@ network::IPAddress WiFiComponent::wifi_gateway_ip_() {
return network::IPAddress(&ip.gw);
}
network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { return network::IPAddress(dns_getserver(num)); }
void WiFiComponent::wifi_loop_() { this->process_pending_callbacks_(); }
bool WiFiComponent::wifi_loop_() {
this->process_pending_callbacks_();
return true;
}
void WiFiComponent::process_pending_callbacks_() {
// Process callbacks deferred from ESP8266 SDK system context (~2KB stack)
@@ -715,10 +715,10 @@ const char *get_disconnect_reason_str(uint8_t reason) {
}
}
void WiFiComponent::wifi_loop_() {
bool WiFiComponent::wifi_loop_() {
// Fast path: skip dropped count check and pop loop when queue is empty
if (this->event_queue_.empty())
return;
return false;
uint16_t dropped = this->event_queue_.get_and_reset_dropped_count();
if (dropped > 0) {
@@ -730,6 +730,7 @@ void WiFiComponent::wifi_loop_() {
wifi_process_event_(data);
delete data; // NOLINT(cppcoreguidelines-owning-memory)
}
return true;
}
// Events are processed from queue in main loop context, but listener notifications
// must be deferred until after the state machine transitions (in check_connecting_finished)
@@ -777,10 +777,10 @@ int32_t WiFiComponent::get_wifi_channel() { return WiFi.channel(); }
network::IPAddress WiFiComponent::wifi_subnet_mask_() { return {WiFi.subnetMask()}; }
network::IPAddress WiFiComponent::wifi_gateway_ip_() { return {WiFi.gatewayIP()}; }
network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { return {WiFi.dnsIP(num)}; }
void WiFiComponent::wifi_loop_() {
bool WiFiComponent::wifi_loop_() {
// Fast path: skip dropped count check and pop loop when queue is empty
if (this->event_queue_.empty())
return;
return false;
uint16_t dropped = this->event_queue_.get_and_reset_dropped_count();
if (dropped > 0) {
@@ -792,6 +792,7 @@ void WiFiComponent::wifi_loop_() {
wifi_process_event_(event);
delete event; // NOLINT(cppcoreguidelines-owning-memory)
}
return true;
}
} // namespace esphome::wifi
@@ -303,7 +303,7 @@ network::IPAddress WiFiComponent::wifi_dns_ip_(int num) {
// Connect state listener notifications are deferred until after the state machine
// transitions (in check_connecting_finished) so that conditions like wifi.connected
// return correct values in automations.
void WiFiComponent::wifi_loop_() {
bool WiFiComponent::wifi_loop_() {
// Handle scan completion
if (this->state_ == WIFI_COMPONENT_STATE_STA_SCANNING && !cyw43_wifi_scan_active(&cyw43_state)) {
this->scan_done_ = true;
@@ -365,6 +365,7 @@ void WiFiComponent::wifi_loop_() {
#endif
}
}
return true;
}
void WiFiComponent::wifi_pre_setup_() {}